生成没有排列的序列

时间:2013-12-11 14:21:59

标签: algorithm math permutation

我在整数中使用两位数来表示一个元素。即3345512代表四个元素[3,34,55,12]。接下来,我重复向整数添加一个以获得另一个元素序列。当生成这样的序列时,我得到相同序列的排列,即3341255 = [3,34,12,55],在我的情况下等于数字3345512 = [3,34,55,12]。所以我想避免我已经遇到的序列的排列。我不希望存储数字,因为它们变得非常大(10^30和更多)。我试图使用布隆过滤器,但它无法处理元素的数量。是否有一个简单的解决方案来生成没有排列的序列?

[编辑]这是一个很小的python脚本,应该可以工作。为了更好地理解,我使用if s[idx] == 9:代替if s[idx] == 99:的单个数字 如果你有一个更简单的解决方案,我会接受它作为答案。

import time
s = [1]
while True:
    idx = 0
    while not idx+1 == len(s) and not s[idx] < s[idx+1]:
        s[idx] = 1
        idx += 1
    if s[idx] == 9:
        s[idx] = 1
        s.append(1)
    else:
        s[idx] += 1
    print repr(s)
    time.sleep(0.7)

2 个答案:

答案 0 :(得分:2)

你要求的是组合而不是排列。看起来您正尝试从100个列表中获取4个项目的唯一组合。也就是说,您的可能值为0099

您可以使用嵌套循环生成所有组合,如下所示:

for (i = 0 to 96)
    for (j = i + 1 to 97)
        for (k = j + 1 to 98)
            for (l = k + 1 to 99)
                write i, j, k, l

这保证你不会得到相同的组合。

您还会在生成的组合中注意到:

i < j < k < l

如果你的序列始终满足不等式,那么你就不会得到重复的组合。

因此永远不会生成您的示例3345512。它将是3123455

鉴于此,当您从3123499增加时,您不会转到3123500,而是转到3123536。基本上,如果溢出一个位置,则递增下一个位置,原始位置变为(下一个位置+ 1)。因此3999999增加到4050607

显然,你不能用简单的整数增量来做到这一点。我建议使用4字节值和一点逻辑。

这是另一种方法。

想象一下,您的字母表只有4个字符[0, 1, 2, 3]。共有16种可能的独特组合。您需要两个项目的独特组合。

现在,考虑一个可以保存值0到15的4位数。您可以将该数字映射到唯一组合,以便数字3(0011二进制)对应于组合0,1。即位设置为0并设置位1。应该清楚的是,设置2位的数字对应于唯一的2字符组合。对于4个项目的字母表中的2组合,我们有:

0, 1  (0011)
0, 2  (0101)
0, 3  (1001)
1, 2  (0110)
1, 3  (1010)
2, 3  (1100)

这样,您可以递增一个整数,看它是否设置了两个位,然后从设置位转换为字母表中的字符。

从一组100个字符中选择4种组合,你可以做同样的事情。使用100位数字有点困难但并非不可能。由于您只是递增,因此可以使用一对64位数字来完成。

确定设置了多少位很容易做到天真的方式。 Bit Twiddling Hacks页面显示了几种更快的方法。

有几种方法可以解决这个问题,所有这些方法都可以参数化,从n个项目列表中选择唯一的k组合。

答案 1 :(得分:0)

要检查给定的序列是否已经生成并且可以跳过,您应该生成当前序列的“先前”排列,如果从零开始计算将生成,并将其与起始编号进行比较。

您可以通过以下方式找到此排列:

如果数字处于递增的顺序 - 例如[3] [4] [5] [6] - 你可以停止,因为这些数字没有更小的排列。

如果序列有一些非增加部分 - 例如[3] [5] [4] [8] [6] [7] [8] [9]。该序列具有两个非增加部分。 5-4和8-6。

找到比其后续号码更大的最后一个号码。这是第8个。

[3] [5] [4] [8] [6] [7] [8] [9]

找到8后面最大的数字,实际上更小。这是7。

[3] [5] [4] [8] [6] [7] [8] [9]

将7移动到8的位置,并将所有其他数字按降序排列。

[3] [5] [4] [7] [9] [8] [8] [6]

现在,如果此序列小于起始编号 - 您知道它尚未生成。否则你可以跳过它。