重复排列而不分配内存

时间:2010-10-16 20:58:48

标签: algorithm permutation

我正在寻找一种算法来生成所有排列,重复列表中的4个元素(长度2-1000)。

Java implementation

问题是来自上面链接的算法为计算分配了太多内存。它创建一个具有所有可能组合长度的数组。例如,我的例子是4 ^ 1000。所以我得到了堆空间异常。

谢谢

3 个答案:

答案 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;
}