给定了N,那么就可以通过“小于N的数在每一位上可能出现1的次数”之和得到结果f(N)。
先从简单的情况开始观察。
先看1位数的情况
如果N=3,那么从1到3的所有数字:1、2、3,只有个位数字上可能出现1,而且只出现一次,
同理,如果N是1位数,且N>=1,那么f(N)=1,如果N=0,则f(N)=0。
再看2位数的情况
如果N=13,那么从1到13的所有数字:1、2、3、4、5、6、7、8、9、10、11、12、13,个位和十位的数字上都可能出现1,通过分析,个位出现1的次数有2次(1、11),十位出现1的次数由4次(10、11、12、13),所以f(N)=2+4=6。(注意,11这个数,虽然在个位和十位上都出现了1,但是11恰好被个位和十位分别计算了一次,所以不用特殊处理。)
接着分析3位数的情况
如果N=123:
个位出现1的个数为13: 1,11,21,...,91,101,111,121
十位出现1的个数为20: 10 ~ 19,110 ~ 119
百位出现1的个数为24: 100 ~ 123
所以f(N)=13+20+24=57。
同理我们可以再分析4位数,5位数。你也可以自己推一推,总结规律。
总结如下:
假设N=abcd,这里a,b,c,d分别是千位,百位,十位,个位上的数字。
如果要计算十位上(c)出现1的次数,它将受到三个因素的影响:十位上的数(c),十位以上的数字(ab),十位以下的数字(d)。
if(c==0) f(N) += ab*10; //比如1201
else if(c==1) f(N) += ab*10 + d+1; //比如1211
else f(N) += (ab+1) * 10; //比如1221
通过上面的归纳和总结,只要分析N就可以得到f(N),避开了从1到N的遍历,时间复杂度O(ln(N)/ln(10)+1)。