zoukankan      html  css  js  c++  java
  • 《编程之美》“1的数目”的另一个解法

    问题:给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数f(N)。

    书上给的最优解,考虑十进制表示的每一位,对于0,1,其他这三种情况分开讨论,然后结合高位数字、当前位数字、低位数字计算。

    我想到的是另一个解法,时间复杂度一样,但思路更简单一些:

       1
       2
       3
    ....
      10
      11
      12
    ....
     100
     101
     102
    ....
    1000
    1001
    1002

    个位数的1:每10个有1个

    十位数的1:每100个有10个

    百位数的1:每1000个有100个

    千位数的1:每10000个有1000个

    ...

    逐位统计。例如百位数上的1,先看有几个整千,计算100*(N/1000)。然后考虑剩余的不到1000的部分,从100算起有几个(注意不到100的不算,大于等于200的也不算)。两部分加起来即可。

    C++17代码实现如下:

    #include <algorithm>

    int
    f(int n) { int iCount = 0; int iFactor = 1; while (n / iFactor != 0) { int iFactorH = iFactor * 10; iCount += iFactor * (n / iFactorH) + std::clamp(n % iFactorH - iFactor + 1, 0, iFactor); iFactor *= 10; } return iCount; }

    结果验证过是一致的。

    顺便打印了一下所有f(N)=N的案例:

    1
    199981
    199982
    199983
    199984
    199985
    199986
    199987
    199988
    199989
    199990
    200000
    200001
    1599981
    1599982
    1599983
    1599984
    1599985
    1599986
    1599987
    1599988
    1599989
    1599990
    2600000
    2600001
    13199998
    35000000
    35000001
    35199981
    35199982
    35199983
    35199984
    35199985
    35199986
    35199987
    35199988
    35199989
    35199990
    35200000
    35200001
    117463825
    500000000
    500000001
    500199981
    500199982
    500199983
    500199984
    500199985
    500199986
    500199987
    500199988
    500199989
    500199990
    500200000
    500200001
    501599981
    501599982
    501599983
    501599984
    501599985
    501599986
    501599987
    501599988
    501599989
    501599990
    502600000
    502600001
    513199998
    535000000
    535000001
    535199981
    535199982
    535199983
    535199984
    535199985
    535199986
    535199987
    535199988
    535199989
    535199990
    535200000
    535200001
    1111111110

    并不是很多,而且可以看到有抱团的现象。书中证明了这个集合是有限的,最大值就是1111111110。

  • 相关阅读:
    TensorFlow gfile文件操作详解
    ROS学习之日志消息
    typeid().name()获取类型名
    Ubuntu Qt配置QVTKWidget控件
    python-pcl简易文档(不包含自建函数与pcl_grabber包)
    ros源码之初始化函数init()调用的几个初始化函数
    奇异值分解(SVD)原理
    ROS节点的初始化及退出详解(ros::init、SIGINT、ros::ok、ros::NodeHandle)
    ROS Nodehandle句柄
    C++可变参数模板
  • 原文地址:https://www.cnblogs.com/xrst/p/13252113.html
Copyright © 2011-2022 走看看