原题
求出1-13的整数中1出现的次数,并算出100-1300的整数中1出现的次数?为此他特别数了一下1-13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路
统计每一位(个位,十位,百位。。。。)上1出现的次数。
设定i为整数点(取值为10, 100, 1000。。。。)对应为n的个位, 十位,百位(该位置处)上包含多少个1进行分析。
根据i对n进行分割,令int a = n/i, b = n % i;
以i = 100 进行分析,即分析<= n的数字当中有多少个百位上为1。
1. 百位对应的数字>= 2
以n = 31244为例进行分析,a = n/i = 312, b = n % i = 44。
此时,百位上为1的数字个数为 (a / 10 + 1) * 100。
解释一下:对于百位为1的数字有100-199,共计100个。更高位(千位,万位。。。)可以是0-(a/10+1),对应为本例当中的0-31共32个。这些数字都包含完整的区间(100个)
2. 百位对应的数字==1
以n = 31144为例进行分析,a = n/i = 311, b = n % i = 44。
此时,百位上为1的数字个数为 (a / 10) * 100 + (b+1)。
解释一下:对于百位为1的数字有100-199,共计100个。更高位(千位,万位。。。)为0-(a/10)的数字 有完整的区间,即100个,对应为本例当中的0-30共31个。<= n的数字当中,以31开头的数字中,百位为1的数为31100-31144,共(b+1)个。
3. 百位对应的数字==0
以n = 31044为例进行分析,a = n/i = 310, b = n % i = 44。
此时,百位上为1的数字个数为 (a / 10) * 100。
解释一下:对于百位为1的数字有100-199,共计100个。更高位(千位,万位。。。)为0-(a/10)的数字 有完整的区间,即100个,对应为本例当中的0-30共31个。
4. 优化
当然分析已经完成了,多个if,else就可以了,但是a / 10 和 a/ 10 + 1是可以优化的。
只需要写成(a + 8)/10就可以了。
5. 代码
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int count=0;
int i=1;
for(i=1;i<=n;i*=10)
{
//i表示当前分析的是哪一个数位
int a = n/i,b = n%i;
count=count+(a+8)/10*i+(a%10==1? 1 : 0)*(b+1);
}
return count;
}
}