剑指43- 整数中1出现的个数 找规律解法

题目详情

这里牛客网上的叙述及其的敷衍,还是力扣上的详细很多,输入的是正整数,因为n可以很大,所以要考虑时间复杂度,不能O(N)哦。
在这里插入图片描述

题解

1的个数
针对这题,首先要注意一点在于:题目是统计1的个数,而不是统计含1的数字数。所以11不是一次,而是两次,因为出现了两个1。这里需要特别的注意,否则很容易弄错。

需要找规律
对于一个数n,我们自然不能去遍历1-n中的每个数,去统计每个数的1的个数,进行累加,这样的时间复杂度太高,要超时。
所以我们需要一种有规律的方式来解决,来快速的知道,n它有多少个1

规律
我们研究一下0-9,发现这其中有1个1
10-19,这里有11个1(11有两个1),这里可以分成10-19在十位上有1个1,而11在个位上有一个1
20-29有1个1
···
后面的都是只有一个1
所以0-99内统计一下有20个1
然后同样的方式,我们来统计0-999(1000以内)有多少个1
我么分成000-099,100-199,···900-999
这样来计算,先统计十位、个位的1,就是20*10=200
而100-199是百位上有1,所以有100个1
故000-999中有200+100 = 300个1

然后再类推,10000以内(不包含10000本身)有4k个1,100000以内有5w个1
所以便可以总结出规律,100···00(level个0),则有unit = level*10^(level-1) 个1

如此,我们便获得了这种整的数中的1的个数的规律

不过这里我们暂时只考虑了1000···0这种情况
至于X00···00这种呢
其实也很好办,就是X00···000,当X>1时,一定是包含1xxxxxxx的,所以我们先算基本的个数
X*unit,然后再加上1开头的,1xxxxxxxx的个数就行,也就是10^level个1。总的加起来就ok

如此便是求很整的数的1的个数

对于一个不那么整的数的逻辑
比如9667这个数,应该如何计算呢?
逻辑如下

  • 比如9667,9个k,那么首先是9*300+1k = 3700
  • 然后是667,6个百,所以是6*20+100 = 220
  • 然后是67,是6*1+10 = 16
  • 然后是7,是1
  • 结果是3700+220+16+1=3937

我们从高位到低位,一位一位的分别取处理
这里需要注意一点
当我高位为1时,则我所有的1的个数就是高位所含有的1的个数和低位的数值相加
例如1677这个数,
我需要计算1k以内的所有1的个数,
然后1000-1677的千位上1的个数,(重点)
最后才是1000-1677的百位,十位,个位的1的个数

代码

public class Solution {
    
    
    public int NumberOf1Between1AndN_Solution(int n) {
    
    
        if(n<1) return 0;
        int res = 0;
        //进行拆分
        while(n!=0){
    
    
            int mod = n%((int)Math.pow(10,(int)Math.log10(n)));
            String str = String.valueOf(n);
            if(n>9&&str.charAt(0)=='1') res+=mod+1;//保证一定是十位数以上的才行
            res += getOneNum(n-mod);
            n = mod;
        }
        return res;
    }

    //获得整的数中的1的个数
    private int getOneNum(int n){
    
    
        if(n<10) return n>=1 ? 1 : 0;//个位数
        //下面都是整的,10,200,3000这种
        int level = 0;//统计级别
        while(n>=10){
    
    
            n /= 10;
            level++;
        }
        //计算基本单位
        int unit = level*(int)Math.pow(10,level-1);
        int res = n * unit +(n>1?(int)Math.pow(10,level):0) ;
        return res; 
    }
    
}

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/113823530