zoukankan      html  css  js  c++  java
  • 25.在从1到n的正数中1出现的次数[NumberOf1Between1_N]

    【题目】

    输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。

    【分析】

    这是一道广为流传的google面试题。

    普通n*lg(n)的解法。

    【解法1】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     

    /////////////////////////////////////////////////////////////////////////////
    // Find the number of 1 in an integer with radix 10
    // Input: n - an integer
    // Output: the number of 1 in n with radix
    /////////////////////////////////////////////////////////////////////////////
    int NumberOf1(unsigned int n)
    {
        
    int number = 0;
        
    while(n)
        {
            
    if(n % 10 == 1)
                number ++;

            n = n / 
    10;
        }

        
    return number;
    }

    /////////////////////////////////////////////////////////////////////////////
    // Find the number of 1 in the integers between 1 and n
    // Input: n - an integer
    // Output: the number of 1 in the integers between 1 and n
    /////////////////////////////////////////////////////////////////////////////
    int NumberOf1BeforeBetween1AndN_Solution1(unsigned int n)
    {
        
    // T(n) = n*lg(n)
        int number = 0;

        
    // Find the number of 1 in each integer between 1 and n
        for(unsigned int i = 1; i <= n; ++ i)
            number += NumberOf1(i);

        
    return number;
    }

    【解法2】

    更加巧妙的lg(n)的解法。

    简单的方法就是按照给位进行分析:

    在个位出现1的个数=n/10+(个位=0,0;个位>1,1;个位=1,低0位+1);

    十位位出现1的个数=n/100*10+(十位=0,0;十位>1,10;十位=1,低一位+1);

    百位出现1的个数=n/1000*100+(百位=0,0;百位>1,100;百位=1,低两位+1);

    等等。

    算法的复杂度仅仅和位数有关。

    设第i位出现1的个数为s(i),N为输入整数n的位数。则总和sum= s(1)+…s(i)+…s(N)即为所求。

    设bi为整数n的第i位数字,第i位之后的剩余数字为ri;

    s(i) = A + B

    A = n/10i*10i-1

    bi=( n/10i-1)%10

    ri= n/10i-1

    b(i)==0 ,则B=0

    b(i)==1 ,则B=ri+1

    b(i)>1 ,则B=10i-1

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     

    int PowerBase10(unsigned int n)
    {
        
    // 10^n
        int result = 1;
        
    for(unsigned int i = 0; i < n; ++ i)
            result *= 
    10;

        
    return result;
    }

    int b10(unsigned int n)
    {
        
    return PowerBase10(n);
    }

    int NumberBitCount(unsigned int n)
    {
        
    int N = 0;
        
    while(n)
        {
            n = n / 
    10;
            N++;
        }
        
    return N;
    }

    int NumberOf1BeforeBetween1AndN_Solution2(unsigned int n)
    {
        
    // T(n) = o(N) = o(lgn)
        int N = NumberBitCount(n);
        
    int si, sum = 0;
        
    int A, B, bi, ri;
        
    for (int i = 1; i <= N; i++)
        {
            A = n / b10(i) * b10(i - 
    1);
            bi = n / b10(i - 
    1) % 10;
            ri = n % b10(i - 
    1);
            
    if (bi == 0)
            {
                B = 
    0;
            }
            
    else if (bi == 1)
            {
                B = ri + 
    1;
            }
            
    else if (bi > 1)
            {
                B = b10(i - 
    1);
            }
            si = A + B;
            sum += si;
        }

        
    return sum;
    }

    【参考】

    http://zhedahht.blog.163.com/blog/static/25411174200732494452636/

    http://www.cnblogs.com/GoAhead/archive/2012/05/28/2521415.html

    http://blog.csdn.net/sjf0115/article/details/8600599

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    hdu 1823 Luck and Love 二维线段树
    UVA 12299 RMQ with Shifts 线段树
    HDU 4578 Transformation 线段树
    FZU 2105 Digits Count 线段树
    UVA 1513 Movie collection 树状数组
    UVA 1292 Strategic game 树形DP
    【ACM】hdu_zs2_1003_Problem C_201308031012
    qsort快速排序
    【ACM】nyoj_7_街区最短路径问题_201308051737
    【ACM】nyoj_540_奇怪的排序_201308050951
  • 原文地址:https://www.cnblogs.com/hellogiser/p/3738812.html
Copyright © 2011-2022 走看看