计算整数间隔(或整数数组)中每个数字的出现次数

时间:2018-10-19 20:16:51

标签: c++

使用循环,如何查找整数间隔[n,m]中每个数字的出现?

例如:

  • 输入n,m = [19,23] = 19,20,21,22,23

  • 输出应为:

0次出现:1次

1次:2次

2次:5次

3次:1次等。

#include <iostream>
using namespace std;
int main()
{
 int i, j, z, count, n, m;
cin >>n >>m;

for(int i=0; i<10; i++)   // LOOP FOR DIGITS
    {
    cout << i <<"occurences: ";

    count=0;    
    for(int j=n; j<m; j++)  // LOOP INTEGER INTERVAL  
        {
        while (z!=0)  
            {
                z = j % 10;  // LAST DIGIT OF FIRST NUMBER IN INTERVAL
                if (z == i) count++;
                z /= 10;        
            }
        }
    cout << count <<" times"<< endl;
    }
}

我的代码每个数字返回0次,错误在哪里?

5 个答案:

答案 0 :(得分:2)

您无需在范围上循环10次。

   int n, m;
   cin >> n >> m;

   counts = int[10];
   for(int i = 0; i < 10; ++i) {
      counts[i] = 0;
   } 

   for(int j = n; j <= m; j++) {
            int z = j; 
            do {
                int digit = z % 10;  // LAST DIGIT OF FIRST NUMBER IN INTERVAL
                counts[digit]++;
                z /= 10;        
            } while (z != 0);
   }

   for(int i = 0; i < 10; ++i) {
      cout << i << " occurrences " << counts[i] << " times";
   } 

答案 1 :(得分:2)

您可以使用std :: stringstream来获取数字中的每个数字,如下所示:

constexpr int n = 19;
constexpr int m = 23;
std::array<int, 10> digit_count = {0};

for (int i = n; i <= m; i++)
{
    std::stringstream s;
    s << i;
    unsigned char digit;
    while (s >> digit) digit_count[digit - '0']++;
}

答案 2 :(得分:1)

我看到的一些问题:

z = j % 10;

您需要在while循环之外将z初始化为j。您还想获取mod而不是为其设置z。尝试将结果放入temp变量中,而不要放入z中。

您的for循环不包含最后一个数字。 for(int j=n; j<m; j++)应该是j<=m

    z = j;
    while (z!=0)  
     {
            int mod = z % 10;  // LAST DIGIT OF FIRST NUMBER IN INTERVAL
            if (mod == i) count++;
            z /= 10;        
        }
    }

此最终代码给出了正确的结果:

#include <iostream>
using namespace std;
int main()
{
 int i, j, z, count, n, m;
cin >>n >>m;

    for(int i=0; i<10; i++)   // LOOP FOR DIGITS
    {
    cout << i <<" occurences: ";

    count=0;    
    for(int j=n; j<=m; j++)  // LOOP INTEGER INTERVAL  
        {

          z = j;
        while (z!=0)  
            {
                int mod = z % 10;  // LAST DIGIT OF FIRST NUMBER IN INTERVAL
                if (mod == i) count++;
                z /= 10;        
            }
        }
    cout << count <<" times"<< endl;
    }
}

 19 23
0 occurences: 1 times
1 occurences: 2 times
2 occurences: 5 times
3 occurences: 1 times
4 occurences: 0 times
5 occurences: 0 times
6 occurences: 0 times
7 occurences: 0 times
8 occurences: 0 times
9 occurences: 1 times

答案 3 :(得分:1)

基本上,模运算用于检索任何数字的最低有效位。将该数字除以基数将删除最低有效位,使下一位成为新的最低有效位。

int main(int argc, char *argv[])
{
    int radix = 10;
    int x, y;

    printf("Lower bound: ");
    scanf("%d, &x);

    printf("Upper bound: ");
    scanf("%d, &y);

    int digits[radix];
    count_digit_occurence(x, y, radix, digits);

    int i;
    for (i = 0; i < radix; ++i)
    {
        int occ = digits[i];
        printf("%d occurred %d times\n", i, occ);
    }
}

void count_digit_occurence(int x, int y, int radix, int digits[radix])
{
    int i, n;
    for (i = x; i <= y; ++i)
    {
        n = i;
        while (n > 0)
        {
            ++(digits[n % radix]);
            n /= radix;
        }
    }
}

答案 4 :(得分:0)

到目前为止,所有答案最多为算法提供了O(m-n)的复杂度,即从nm的距离是线性的。在这里,我提供了一种具有对数复杂度的方法。基本思想是先考虑每个数字的最后一位,然后考虑倒数第二个,等等。

为了简化代码,我稍作更改,并考虑范围[n, m-1],即排除m

此范围内有m-n个数字;如果这是10的倍数,则每个后一位数字恰好发生(m-n)/10次。否则,我们必须考虑边缘问题。以下例程将countunit(含)范围内的所有数字中最后数字的出现次数加到n m-1上。

void count_last_digits(int n, int m, std::array<int,10> count&, int unit=1)
{
    // 1 increment n until it has the same last digit as m
    for(int dn=n%10, dm=m%10; n<m && dn!=dm; dn=++n%10)
        count[dn] += unit;
    // 2 add unit*(m-n)/10 to all counts
    if(int cnt = unit*(m-n)/10)                     // avoid to add nothing
        for(int d=0; d!=10; ++d)
            count[d] += cnt;
}

一旦我们计算了最后一位,我们计算了倒数第二位,等等。首先,我们需要一个仅计算单个数字的助手功能

void count_digits(int x, std::array<int,10> &count, int unit=1)
{
    for(; x; x/=10)
        count[x%10] += unit;
}

要处理倒数第二个数字,我们首先修剪(使用此辅助函数)间隔,以使nm均为10的倍数,然后将二者均除以10,再乘以计数单位乘以10,然后递归

std::array<int,10> count_all_digits(int n, int m)
{
    std::array<int,10> count={0};
    for(int unit=1; n<m; n/=10,m/=10,unit*=10) {
        // count last digits
        count_last_digits(n, m, count, unit);
        // increment n to the next multiple of 10, but not above m
        if(int inc = std::min(10-(n%10), m-n)) {
            count_digits(n/10, count, unit*inc);
            n += inc;
        }
        // decrement m to the previous multiple of 10, but not below n
        if(int dec = std::min(m%10, m-n)) {
            count_digits(m/10, count, unit*dec);
            m -= dec;         // not really necessary
        }
    }
    return count;
}

函数count_last_digits()count_digits()分别具有复杂度O(1)O(ln(x))。两者都被称为O(ln(m))次,因此后者主导了整体复杂度O(ln(m)^2)

请注意,这些功能假定0 < n <= m,即不允许n<=0