C中数字的独特组合

时间:2015-02-23 21:09:07

标签: c algorithm digits

我需要在C中设计一个算法来计算0到1,000,000的唯一数字组合。例如,当出现13时,31将不包括在此序列中。任何人都可以帮我找到一个算法来描述这个吗?该系列的前几个数字将是:

 1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,22,23,24,25,26,27,28,29,33,etc

谢谢!

编辑 - 抱歉,忘记提及零不包括

2 个答案:

答案 0 :(得分:6)

#include <stdio.h>
int main(void) {
    int i, n;
    for (n = 1; n < 1000000; n++) {
        for (i = n;;) {
            if (i / 10 % 10 > i % 10) break;
            if ((i /= 10) == 0) { printf("%d\n", n); break; }
        }
    }
}

系列中的5004个数字,从0到1000000

更快的版本:

#include <stdio.h>
#include <stdlib.h>

static long long enumerate(char *p, int i, int n, int digit, int silent) {
    long long count = 0;
    if (i >= n) {
        if (!silent) printf("%s\n", p);
        return 1;
    }
    for (p[i] = digit; p[i] <= '9'; p[i]++)
        count += enumerate(p, i + 1, n, p[i], silent);
    return count;
}

int main(int argc, char **argv) {
    char array[256];
    int i, n;
    int max = (argc > 1) ? strtol(argv[1], NULL, 0) : 6;
    int silent = 0;
    long long count = 0;
    if (max < 0) {
        max = -max;
        silent = 1;
    }
    array[sizeof(array)-1] = '\0';
    for (n = 1; n <= max; n++) {
        count += enumerate(array + sizeof(array) - 1 - n, 0, n, '1', silent);
        if (silent)
            printf("%lld combinations between 0 and 1E%d\n", count, n);
    }
}

使用正数调用以枚举组合,使用负数来计算它们。

答案 1 :(得分:2)

函数next将数组a更新为下一个数字,返回底部数字的值。 main函数遍历序列,一旦高位数为10就停止(因为一旦数组用完,next只是递增最高位数。)

算法,用单词和忽略边界检查,可以描述为&#34;找到下一个数字,在底部数字加1,如果溢出,找到忽略底部数字的下一个数字,然后复制新的底部数字。&#34;

#include <stdio.h>

int next(int *a, size_t len) {
    if (*a == 9 && len > 1) {
        *a = next(a-1, len-1);
    } else {
        *a += 1;
    }
    return *a;
}

#define N 6

int main(int argc, char *argv[]) {
    int a[N] = {0};
    while (next(a+N-1, N) != 10) {
        for (int i = 0; i < N; i++) {
            if (a[i] != 0) printf("%d", a[i]);
        }
        printf("\n");
    }
    return 0;
}

您可以在O(N)时间内计算解决方案(其中N是数字位数)。如果K(n,d)是正数为n位的解的个数,且其最高位为9-d,则K(0,d)= 1,K(n + 1,d)= K(n, 0)+ K(n,1)+ ... + K(n,d)。然后,具有n个或更少位的解的数量是K(1,8)+ K(2,8)+ ... + K(n,8)。这些观察结果产生了这种动态编程解决方案:

int count(int n) {
    int r[9] = {1};
    int t = 0;
    for (int i = 0; i < n+1; i++) {
        for (int j = 1; j < 9; j++) {
            r[j] += r[j-1];
        }
        t += r[8];
    }
    return t - 1;
}

int main(int argc, char* argv[]) {
    printf("there are %d numbers.\n", count(6));
    return 0;
}

给出:

there are 5004 numbers.