码迷,mamicode.com
首页 > 其他好文 > 详细

32 - 从 1 到 n 整数中 1 出现的次数

时间:2015-08-08 22:53:10      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:

问题:
给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数。
例如:
N= 2,写下1,2。这样只出现了1个“1”。
N= 12,我们会写下1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12。这样,1的个数是5。


直观思路是,逐个计算出1 ~ N 这 N 个数含有 1 的个数。
如 1 ~ 12345 :判断最后 1 位是否为 1,然后每一次右移一位,重复上述步骤。
判断 1 个数的复杂度O(logN),总时间复杂度O(N?logN)

改进思路:能否直接计算出给定 1 ~ N 的 1 出现次数:
如 12,个位出现 1 的次数为2,十位出现 1 的次数是 3,则总次数为 5
如 23,个位出现 1 的次数为 3 (1,11,21),十位出现 1 的次数为 10 (11,12,…,19),则总次数为 13
即只要求出每一位可能出现 1 的次数,则能够求出 1 ~ n 出现 1 的次数。

我们通过逐位判断的方式,以百位数字为例:

  • 如果百位数字是 0 则百位出现 1 的次数,只由更高位决定:
    如 12045:百位是 1 的次数
    100~199
    1100~1199
    2100~2199
    。。。
    11,100~11,199
    每一行含有 100 个,共 12 行;故百位出现 1 的次数 更高位数字(12) * 当前位数(100)

  • 如果百位数字是 1 则百位出现 1 的次数,不仅由更高位决定,还和当前位的低位有关
    如 12145:百位是 1 的次数,除了上述高位决定的 12*100 次
    低位部分 12,100 ~ 12,145 百位出现 1 的次数等于低位数字(45) + 1

  • 如果百位数字大于 1 (2~9),则百位出现 1 的次数,只由更高位决定
    12345 : 百位是 1 的次数
    100~199
    1100~1199
    2100~2199
    。。。
    11,100~11,199
    12,100~12,199
    每一行含有 100 个,共 13 行;故百位出现 1 的次数 更高位数字加一(12+1) * 当前位数(100)

上述算法的时间复杂度:O(logL),L 为 n 的10进制的位数

#include <iostream>
using namespace std;
int Counts1OfN(int n) {
    int counts = 0;
    int base = 1;
    int low = 0; //低位数字
    int cur = 0; //当前位
    int high = 0; //高位数字
    while (n/base > 0) {
        //如12345:base = 100, cur = 3, low = 45, hight 12
        low = n % base;
        cur = (n / base) % 10;
        high = n / (base*10);
        switch(cur) {
            case 0:
                counts += high*base;
                break;
            case 1:
                counts += high*base + (low+1);
                break;
            default:
                counts += (high+1)*base;
        }
        base *= 10;
    }
    return counts;
}

int main()
{
    int nums[] = {4,13,33,103,113,123,9999,33342124};
    for (int i = 0; i < sizeof(nums)/sizeof(nums[0]); i++) {
        cout << "0 ~ " << nums[i] << " 包含 1 的个数:" << Counts1OfN(nums[i]) << endl;
    }
}

结果:

1 ~ 4 包含 1 的个数:1
1 ~ 13 包含 1 的个数:6
1 ~ 23 包含 1 的个数:13
1 ~ 33 包含 1 的个数:14
1 ~ 103 包含 1 的个数:25
1 ~ 113 包含 1 的个数:40
1 ~ 123 包含 1 的个数:57
1 ~ 9999 包含 1 的个数:4000
1 ~ 33342124 包含 1 的个数:34077658

参考:《编程之美》

版权声明:本文为博主原创文章,未经博主允许不得转载。

32 - 从 1 到 n 整数中 1 出现的次数

标签:

原文地址:http://blog.csdn.net/quzhongxin/article/details/47362993

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!