原始列表 X 有 n 个项目。有 2**n 个可能的子列表,因为每个项目都会或不会出现在子列表中:每个项目都会在可能的子列表的枚举中添加一个位。您可以查看此 n 位位字的枚举。
由于您只想要具有 k 个项目的子列表,因此您对设置了 k 位的位字感兴趣。一个实用的算法可以从 X 中挑选(或不挑选)第一个元素,然后考虑到所选项目的累积数量,然后递归到 X 的最右边的 n-1 个子串。由于 X 列表按顺序处理,Y 列表也将按顺序处理。
#include <stdio.h>
#include <string.h>
unsigned pick_k_from_n(char target[], char src[], unsigned k, unsigned n, unsigned done);
unsigned pick_k_from_n(char target[], char src[]
, unsigned k, unsigned n, unsigned done)
{
unsigned count=0;
if (k>n) return 0;
if (k==0) {
target[done] = 0;
puts(target);
return 1;
}
if (n > 0) {
count += pick_k_from_n(target, src+1, k, n-1, done);
target[done] = *src;
count += pick_k_from_n(target, src+1, k-1, n-1, done+1);
}
return count;
}
int main(int argc, char **argv) {
char result[20];
char *domain = "OmgWtf!";
unsigned cnt ,len, want;
want = 3;
switch (argc) {
default:
case 3:
domain = argv[2];
case 2:
sscanf(argv[1], "%u", &want);
case 1:
break;
}
len = strlen(domain);
cnt = pick_k_from_n(result, domain, want, len, 0);
fprintf(stderr, "Count=%u\n", cnt);
return 0;
}
删除递归留给读者作为练习。一些输出:
plasser@pisbak:~/hiero/src$ ./a.out 3 ABBA
BBA
ABA
ABA
ABB
Count=4
plasser@pisbak:~/hiero/src$