zoukankan      html  css  js  c++  java
  • 给一个正整数n,计算从1-n中出现1的次数

    如12出现1的次数为5,分别是:1,10,11,12

    一般做法:从1-n遍历,计算每一个数中每一位出现1的次数

    function count(num){    
        var n=0;
        for(var i=1;i<=num;i++){
            n+=Number(i);
        }
        console.log(n);
    }
    function Number(i){
        var number=0;
        while(i!=0){
            if(i%10==1){
                number+=1;
            }
            i=parseInt(i/10);
        }
        return number;
    }
    var num=1234;
    count(num);

    这种做法对每一个数字都要做除法和求余运算,以求出该数字中1出现的次数。但是当输入的n非常大时需要大量的计算,运算效率不高。所以需要进行优化。

    法二:分析规律  计算每一位出现1的次数

    (1)1位数情况

    如n=5;  出现1的次数为1

    (2)2位数的情况

    如n=13

    个位上出现1的有:1,11

    十位上出现1的有:10,11,12,13

    f(n)=2+4=6;

    如n=23

    个位出现1的有:1,11,21

    十位出现1的有:10,11,12,13,14,15,16,17,18,19

    f(n)=3+10=13

    通过对两位数进行分析,我们发现:

    个位出现1的次数不仅和个位数字有关,还和十位数字有关;如果n的个位数大于等于1,则个位出现1的次数为十位数字加1;

    如果个位数字为0,则个位出现1的次数等于十位的数字;

    而十位出现1的次数不仅和十位数有关,还和个位数有关;如果十位数等于1,则十位数出现1的次数为个位数的数字加1,如果十位数大于1,则十位数出现1的次数为10;

    (3)3位数的情况

    如n=123;

    个位出现1的次数13:1,11,21,。。。91,101,111,121 

    十位出现1的次数20:10-19,110-119

    百位出现1的次数24:100-123

    f(n)=13+20+24

    如果要计算百位上出现1的次数,它受三方面影响:百位上的数字,百位以下的数字以及百位以上的数字

    如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100~199,1100~1199,2100~2199,,.........,11100~11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。

    如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100~199,1100~1199,2100~2199,,.........,11100~11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共114个,等于低位数字(113)+1。

    如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100~199,1100~1199,2100~2199,...........,11100~11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。

    function num1(n){
        var count=0;//个数
        var curBit=1;//当前位
        var lowerNum=0;//低位数字
        var curNum=0;//当前位数字
        var higherNum=0;//高位数字
                    
        if(n<=0){
            return 0;
        }
        while(parseInt(n/curBit)!=0){
            lowerNum=n-parseInt(parseInt((n/curBit))*curBit);
            curNum=parseInt((n/curBit)%10);
            higherNum=parseInt(n/(curBit*10));
                        
            //如果当前位为0,出现1的次数由高位决定
            if(curNum==0){
                //等于高位数字乘当前位数
                count+=higherNum*curBit;
            }
            //如果当前位为1,出现1的次数由高位和低位决定
            else if(curNum==1){
                //等于高位数字*当前位数+低位数字+1
                count+=higherNum*curBit+lowerNum+1;
            }
            //如果大于1,出现1的次数由高位决定
            else{
                //(高位数字+1)*当前位数
                count+=(higherNum+1)*curBit;
            }
                        
            //位数向前移一位
            curBit*=10;
        }
        return count;
    }
    console.log(num1(1234));
  • 相关阅读:
    UILabel 设置字体间的距离 和 行与行间的距离
    IB_DESIGNABLE 和 IBInspectable 的使用
    干货博客
    GitHub克隆速度太慢解决方案
    实时(RTC)时钟,系统时钟和CPU时钟
    折腾了好久的vscode配置c/c++语言环境(Windows环境下)
    c语言中的malloc函数
    记录一下关于在工具类中更新UI使用RunOnUiThread犯的极其愚蠢的错误
    记录关于Android多线程的一个坑
    Android中限制输入框最大输入长度
  • 原文地址:https://www.cnblogs.com/xiaoan0705/p/10547088.html
Copyright © 2011-2022 走看看