题目描述
求出1-13的整数中1出现的次数,并算出100-1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路
从低位到高位依此判断出现过1的次数,以百位为例:
1、如果当前位是0,如12034,那么百位出现过1的情况有100-199、1100-1199、2100-2199、…、11100-11199,一共12个区间,每个区间大小100,所以出现了1200次1。可见当前位是0,它出现过1的次数仅由高位(12)决定,即等于高位(12)乘当前位的权重(100)。
2、如果当前位是1,如12134,那么百位出现过1的情况是100-199、1100-1199、2100-2199、…、11100-11199、12100-12134,可以看到此时不仅受高位(12)影响,还受低位(34)的影响。所以当前位是1,它出现过1的次数由高位(12)和低位(34)共同决定,即等于高位(12)乘当前位的权重(100)加低位数字(34)+1(00)。
3、如果当前位大于1,如12234,那么百位出现过1的情况是100-199、1100-1199、2100-2199、…、11100-11199、12100-12199,一共12+1个区间,每个区间大小100,所以出现了1300次1。可见当前位大于1,它出现过1的次数仅由高位(12)决定,即等于高位(12)加1然后乘当前位的权重(100)。
代码(c++)
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
if(n==0) return 0;
int count=0;
for(int i=1;i<=n;i*=10){
int a=n/i;//包括高位和当前位
int b=n%i;//低位
if(a%10>1) count+=(a/10+1)*i;
else if(a%10==1) count+=(a/10)*i+(b+1);
else count+=a/10*i;
}
return count;
}
};