zoukankan      html  css  js  c++  java
  • 剑指offer 计算1到n中所有1出现的次数

        

          如题,显而易见,我们可以依次计算所有数中的1来完成该功能:

    int NumOfOneBetweenN(int n)
    {
        int sum = 0;
        for(int i=1;i<n;++i)
            sum += NumOfOne(i);
        return sum;    
    }
    
    int NumOfOne(int i)
    {
        int sumi = 0;
        while(i)
        {
            if(i%10 == 1)
                sumi++;
            i/=10;    
        }
        return sumi;
    }
    

          时间复杂度为O(n*logn),效率不高。

          那么,换一种思路考虑,计算每个位出现1的次数,当然,要先找到数学规律,这需要归纳推理:

          设输入数字为n,1出现的次数为t,每一位出现的次数为ti.

          n为个位数: 显而易见,  n>=1,t=1;

                      n=0,t=0

                         n为十位数: n=13,个位出现1的情况:1,11, 十位出现1的情况:10,11,12,13       t=2+4=6;

                                           n=23,个位出现1的情况:1,11,21, 十位出现1的情况:10~19        t=3+10=13;

                  n=33,个位出现1的情况:1,11,21,31, 十位出现1的情况: 10~19  t=4+10=14;

                我们发现,当十位数>1,十位出现的次数固定: t10=10;

                   十位数=1,次数由个位大小决定: t10=t1+1;

                   个位数>1,次数由十位大小决定: t1=t10+1.

           n为三位数: n=123,个位出现1的情况:1~91,101~121, 十位数出现1的情况: 10~19,110~119 , 百位出现1的情况: 100~123   t=13+20+24=57;

                n=223,个位出现1的情况:1~91,101~191,201~221, 十位出现1的情况: 10~19,110~119,210~219, 百位出现1的情况: 100~199 t=23+30+100=153;

                我们发现,十位的次数被高位影响,个位的次数也被高位影响,而百位和上面十位>1的情况一样,次数固定,=1的情况又会被低位影响

                不妨,我们可以设一个五位数,我们要计算百位出现1的次数,那么可以把数字分成三部分,百位之前的高位,百位,百位之后的低位.

                1.百位=0,百位出现1的次数只与高位有关.比如12013,百位出现1的情况:00100~00199,01100~01199...11100~11199.共1200个,也就是高位*本位固定后的次数,即12*100;

                2.百位>1,百位出现1的次数只与高位有关.比如12313,百位出现1的情况,00100~00199,01100~01199...12100~12199,共1300个,也就是(高位+1)*1本位固定后的次数,即13*100;

                3.百位=1,百位出现1的次数与高低位都有关.比如12113,百位出现1的情况,00100~00199...11100~11100,还有12100~12113,共1314个,也就是高位*本位固定后的次数+低位+1,即12*100+114

                归纳: 某一位=0的时候,该位出现1的次数被高位决定,即 0该位~(高位-1)该位,共高位*该位固定数;

                  某一位>1的时候,该位出现1的次数被高位决定,即 0该位~高位该位,共(高位+1)*该位固定数;

                 某一位=1的时候,该位出现1的次数被高低位决定,即 0该位~(高位-1)该位 , 该位0~该位低位,共高位*该位固定数+低位+1;

               本质上,其实只有两种情况: 1.ti=0||ti>1,可以被高位按固定次数列举完

                             2.ti=1,被高位按固定次数列举完之后,还有不足固定次数的,由低位决定

    int NumOfOneBetweenN(int n)
    {
        int count = 0;
        int i = 1;
        int cur = 0,after = 0,before = 0;
        
        //循环处理每一位
        while((n/i)!=0)
        {
            cur = (n/i)%10;
            before = n/(i*10);
            after = n - (n/i)*i;
            
            if(cur>1)
                count += (before+1)*i;
            else if(cur==0)
                count += before*i;
            else
                count += before*i + after + 1;
                
            i*=10;                  
        }
        return count;
    }
    

      

              

                  

                  

  • 相关阅读:
    性能测试的bug【杭州多测师】【杭州多测师_王sir】
    Typescript: 当出现错误时,不编译文件成js文件
    git基础命令
    获取页面宽度
    详解linux下的串口通讯开发
    货源清单的配置
    物料在工厂中未被维护
    quota配额配置
    采购组织不对工厂负责
    拓端tecdat:Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用
  • 原文地址:https://www.cnblogs.com/Duikerdd/p/12179314.html
Copyright © 2011-2022 走看看