我正在寻找一种算法来生成所有排列,重复列表中的4个元素(长度2-1000)。
问题是来自上面链接的算法为计算分配了太多内存。它创建一个具有所有可能组合长度的数组。例如,我的例子是4 ^ 1000。所以我得到了堆空间异常。
谢谢
答案 0 :(得分:3)
广义算法,用于延迟评估生成长度为X的所有排列(重复)的一组选择Y:
for I = 0 to (Y^X - 1):
list_of_digits = calculate the digits of I in base Y
a_set_of_choices = possible_choices[D] for each digit D in list_of_digits
yield a_set_of_choices
答案 1 :(得分:2)
如果重复4个符号没有长度限制,有一个非常简单的算法可以满足您的需要。只需将您的字符串编码为二进制数,其中所有2位模式编码四个符号中的一个。要通过重复获得所有可能的排列,您只需枚举“计数”所有可能的数字。这可能很长(超过宇宙的年龄),因为1000个符号将是2000位长。这真的是你想要做的吗?堆溢出可能不是唯一的限制......
下面是一个简单的C实现,它在没有分配内存的情况下枚举所有长度正好为n的重复(n限制为16000,无符号32位)。我向读者留下了枚举最长n的所有重复的练习。
#include <stdio.h>
typedef unsigned char cell;
cell a[1000];
int npack = sizeof(cell)*4;
void decode(cell * a, int nbsym)
{
unsigned i;
for (i=0; i < nbsym; i++){
printf("%c", "GATC"[a[i/npack]>>((i%npack)*2)&3]);
}
printf("\n");
}
void enumerate(cell * a, int nbsym)
{
unsigned i, j;
for (i = 0; i < 1000; i++){
a[i] = 0;
}
while (j <= (nbsym / npack)){
j = 0;
decode(a, nbsym);
while (!++a[j]){
j++;
}
if ((j == (nbsym / npack))
&& ((a[j] >> ((nbsym-1)%npack)*2)&4)){
break;
}
}
}
int main(){
enumerate(a, 5);
}
答案 2 :(得分:0)
你知道如何计算:如果你超过9跳回0并将数字加1,等等1加点1。
所以,如果你有一个长度为N
的列表,每个地点都有K
个项目:
int[] permutations = new int[N];
boolean addOne() { // Returns true when it advances, false _once_ when finished
int i = 0;
permutations[i]++;
while (permutations[i] >= K) {
permutations[i] = 0;
i += 1;
if (i>=N) return false;
permutations[i]++;
}
return true;
}