剑指offer - 整数中1出现的次数(从1到n整数中1出现的次数)

原题

求出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;
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37886086/article/details/89840031
今日推荐