• 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: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    [noip2013]华容道
    [tyvj 1061] Mobile Service (线性dp 滚动数组)
    [bzoj 2726] 任务安排 (斜率优化 线性dp)
    [洛谷 P2365] 任务安排 (线性dp)
    [poj 3666] Making the Grade (离散化 线性dp)
    【模板】manacher算法
    [tyvj 1071] LCIS
    [NOIP 2012] 国王游戏
    [NOIP 2010] 关押罪犯 (二分+二分图判定 || 并查集)
    [NOI 2002] 银河英雄传说 (带权并查集)
  • 原文地址:https://www.cnblogs.com/hellogiser/p/3738812.html
Copyright © 2020-2023  润新知