统计数字问题

统计数字问题

相关问题:count the number of 2s

统计数字问题,见李晓东《计算机算法设计与分析》1-1。
题意为:给定一个数N求从1到N的这N个数中0,1,2,3,4,5,6,7,8,9这10个数字出现的次数。注意,所有的数字没有前导的0。 如6要写成6,而不是 006 ,06这种形式。  

分析如下:
这个分析同《编程之美》但是要扩展下:
我们分别统计在每一个位上数字出现的次数:
假如这个数是 1245,

  1. 我们首先统计 1在 十位上出现的次数 = (12+1)*10 这个很容易能够得出来(分别是 120* 110* 100* .... 000*)注意这里我们算的时候将前导0算在0的记数中,算法最后会去除。
  2. 如果统计4在十位上出现的次数 = (12)*10 + 5 +1。在这里4就是原来数在十位上的数,此是4并没有通过进位到达5所以它的个数不仅与高位有关也和地位有关。
  3. 统计 5在十位上出现的次数 =  (12)*10 由于5大于在十位上的数,125*不可能出现在原来的数中,所以这里的个数仅和高位有关系。即(11. 10.09.到00);
通过以上几条规律可以推测得到各位上数字上出现的次数。但是0的个数不准确,因为我们将前导0也算入进来了。那前导0的个数有多少个呢?如果N是三位数。那么有如下规律:

000 
001
....(9)
009
010
....(90)
099
100
....(900)
999
省略 号右面代表个数。
这个规律很明显,前导0的个数和N的位数有关系。。计算很简单就可以实现。
综合以上规律得到代码如下:

void count_num(int a)
{
    int count[10] = {0};
    int n = 1;
    int zero = 0;
    int weishu = 0;
    while(a/n)
    {
        weishu++;
        int lowp = a - (a/n)*n;
        int curr = (a/(n))%10;
        int highp = a/(n*10);
        for (int i = 0;i<10;i++)
        {
            if (i<curr)
            {
                count[i] += (highp+1)*n;
            }
            else if (i == curr)
            {
                count[i] += (highp)*n;
                count[i] += (lowp+1);

            }
            else
            {
                count[i] += (highp)*n;
            }
        }
        n = n*10;
    }
    int t = 1;
    while(t<=weishu)
    {
        n = n/10 ;
        zero += t*(n-1 -n/10 +1);
        t++;
    }
    count[0] = count[0] -zero;
    for (int i = 0;i <10;i++)
    {
        cout<<i<<" "<<count[i]<<endl;
    }
    
}


你可能感兴趣的:(统计数字问题)