不分配内存的重复排列

发布于 2024-09-28 03:24:15 字数 253 浏览 7 评论 0原文

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

Java实现

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

谢谢

I'm looking for an algorithm to generate all permutations with repetition of 4 elements in list(length 2-1000).

Java implementation

The problem is that the algorithm from the link above alocates too much memory for calculation. It creates an array with length of all possible combination. E.g 4^1000 for my example. So i got heap space exception.

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

厌倦 2024-10-05 03:24:15

用于延迟评估生成一组选择 Y 的长度 X 的所有排列(具有重复)的通用算法:

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 

Generalized algorithm for lazily-evaluated generation of all permutations (with repetition) of length X for a set of choices 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 
陈独秀 2024-10-05 03:24:15

如果 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);
}

If there is not length limit for repetition of your 4 symbols there is a very simple algorithm that will give you what you want. Just encode your string as a binary number where all 2 bits pattern encode one of the four symbol. To get all possible permutations with repetitions you just have to enumerate "count" all possible numbers. That can be quite long (more than the age of the universe) as a 1000 symbols will be 2000 bits long. Is it really what you want to do ? The heap overflow may not be the only limit...

Below is a trivial C implementation that enumerates all repetitions of length exactly n (n limited to 16000 with 32 bits unsigned) without allocating memory. I leave to the reader the exercice of enumerating all repetitions of at most length 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);
}
晨光如昨 2024-10-05 03:24:15

你知道如何计数:在个位上加 1,如果超过 9 则跳回 0 并在十位上加 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;
}

You know how to count: add 1 to the ones spot, if you go over 9 jump back to 0 and add 1 to the tens, etc..

So, if you have a list of length N with K items in each spot:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文