Q:求任意非负整数区间中1出现的次数(从1到n中1出现的次数)
例如:
1-20之间1出现的次数为:1,10,11,12,13,14,15,16,17,18,19共12次
思路:
假如给定一个数字为abcde,c为百位的数字,那么要计算百位出现1的次数,我们会发现有三种不同的情况:
- 如果百位数字为0,则百位出现1的次数由它的高位数字决定。例如12012,百位可能出现1的情况有100–199,1100–1199,2100–2199,…,11100–11199;计算可得1出现的次数为1200个,刚好等于它的高位数字乘它的位数=12*100。因此我们可以归纳得出当该位数字为0时,出现1的次数由它的高位数字决定,等于高位数字乘它的位数。
- 如果百位数字为1,则百位出现1的次数由它的高位数字和它的低位数字共同决定。例如12123,百位可能出现1的情况有100-199,1100-1199,2100-2199,…,11100-11199,高位决定它出现1的次数和上面一样为1200个,还有低位影响的情况为12100-12123,一共124个,等于低位数字(123)+1;因此,归纳出该位为1时,出现1的次数由高位数字和低位数字共同决定,等于高位数字*该位位数+低位数字+1。
- 如果百位数字大于1,则百位出现1的次数由它的高位数字决定。例如12312,百位可能出现1的情况有100-199,1100-1199,2100-2199,…,11100-11199,12100-12199,次数为1300,等于(高位数字+1)*该位位数;因此,归纳出该位大于1时,出现1的次数由高位数字决定,等于(高位数字+1)*该位位数。
代码:
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
int count=0; //计算1出现的次数
int cur=0,high=0,low=0;
int i=1;
while((n/i)!=0)
{
cur=(n/i)%10; //cur为当前位数字
high=n/(i*10); //high为高位数字
low=n-(n/i)*i; //low为低位数字
if(cur==0)
count+=high*i;
else if(cur==1)
count+=high*i+low+1;
else
count+=(high+1)*i;
i=i*10;
}
return count;
}
};