我在整数中使用两位数来表示一个元素。即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)
答案 0 :(得分:2)
你要求的是组合而不是排列。看起来您正尝试从100个列表中获取4个项目的唯一组合。也就是说,您的可能值为00
到99
。
您可以使用嵌套循环生成所有组合,如下所示:
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]
现在,如果此序列小于起始编号 - 您知道它尚未生成。否则你可以跳过它。