• 0~400中1出现了多少次?


         今天小菜无意间在社区看到一个讨论:“0~400中1出现了多少次?”。

         小菜看到大部分网友给出的算法是基于字符串的处理,思路大致是:把所有数字拼接成一个字符串,然后对字符串进行处理,进而获取出现次数。例如以下代码:

     1 /**
     2 *  网友版本
     3 *  找出"1"出现的次数
     4 **/
     5 function numberCount1(n){
     6     var a = []; 
     7     for (var i = 0; i <= n; i++) {
     8          a.push(i);
     9     }  
    10     var s = a.join(''); 
    11     return (s.length - s.replace(/1/g, '').length);
    12 }

         也有高手用位运算处理,无奈太高深,小菜看不懂~~~

         其实如果只考虑400这样规整的整数,是有规律可循的,小菜给出一个通过计算得出出现次数的版本:

    /**
    *  小菜的版本
    *  找出"1"出现的次数
    *  只可以判断除了最高位,其它位全是0的整数。例如1、10、20、400、5000。
    **/
    function numberCount(n){
        var _n = parseInt(n) || 0,
            _z = _n.toString().length-1,
            _w = Math.pow(10,_z),
            _s = _n/_w,
            count = 0;
        
        if(_s > 1){
            count = count + _w;
        }
        
        if(_s === 1){
            count = count + 1;
        }
        
        count = count + (_w/10)*_s*_z;
        
        return count;
    }

         通过字符串处理,当范围比较小的时候,速度、资源消耗还是可以接受的,但是如果数量级比较大,比如0~400000000,用字符串处理,显然效率太低,经过测试,浏览器页面直接崩溃。

         而用小菜给出的算法,计算0~400000000范围内1出现的次数,平均耗时15毫秒左右,但小菜这种算法,只能处理除了最高位,其它位全是0的整数。例如1、10、20、400、5000。

         小菜写这篇文章,不是为了炫耀自己的算法,而是要感谢社区的积极讨论,讨论不仅让我们思路开阔,更让我们变得善于思考。

         通过这个小小的算法,让大家明白:没有最好的算法,只有最合适的,在不同的应用场景,采用恰当的算法,才能真正提高系统效率。

  • 相关阅读:
    Linux下的输入/输出重定向
    strcpy与strncpy的区别
    C++的函数重载
    gtest 学习二
    gtest 学习一
    char* wchar* char wchar转换
    iconv 编译不通过问题
    嵌入式常用库
    驱动编程class_create说明
    libiconv 交叉编译
  • 原文地址:https://www.cnblogs.com/iyangyuan/p/4310628.html
Copyright © 2020-2023  润新知