Python 迭代N个符号的所有L长度序列,包括所有N个符号
在python中执行以下操作的有效方法是什么?Python 迭代N个符号的所有L长度序列,包括所有N个符号,python,algorithm,iterator,Python,Algorithm,Iterator,在python中执行以下操作的有效方法是什么? 给定N个符号,迭代N个符号的所有L长度序列,包括所有N个符号。 顺序并不重要,只要覆盖了所有序列,并且每个序列只覆盖一次 让我们把这个迭代器称为seq(symbols,L)。然后,例如, 列表(seq([1,2,3],2))=[] 列表(seq([1,2,3],3))=[(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)] 列表(seq([1,2,3],4))=[(1,1,2,3),(1,1,3,2),(
给定N个符号,迭代N个符号的所有L长度序列,包括所有N个符号。 顺序并不重要,只要覆盖了所有序列,并且每个序列只覆盖一次 让我们把这个迭代器称为seq(symbols,L)。然后,例如,
列表(seq([1,2,3],2))=[]
列表(seq([1,2,3],3))=[(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)]
列表(seq([1,2,3],4))=[(1,1,2,3),(1,1,3,2),(1,2,1,3) 下面是一个直观但缓慢的实现:
import itertools
def seq(symbols,L):
for x in itertools.product(symbols,repeat=L):
if all(s in x for s in symbols):
yield x
当N较大且L接近N时,会浪费大量精力。例如,当L==N时,使用itertools.permutations()会更好.由于每个序列都需要有所有N个符号,似乎更好的解决方案应该从置换的解决方案开始,然后以某种方式添加额外的重复符号,但我不知道如何在不重复计数的情况下做到这一点(并且不必保存所有以前的输出以检查重复)。一个想法:
import itertools
def solve(size, symbols, todo = None):
if todo is None: todo = frozenset(symbols)
if size < len(todo): return
if size == len(todo):
yield from itertools.permutations(todo) # use sorted(todo) here
# for lexicographical order
return
for s in symbols:
for xs in solve(size - 1, symbols, todo - frozenset((s,))):
yield (s,) + xs
for x in solve(5, (1,2,3)):
print(x)
您可以通过将问题分为两部分来实现这一点:
范围(N)
中的整数。然后,我们可以将多集表示为长度为N的向量,其值是与L相加的非负整数。为了限制多集至少包含每个符号一次,我们要求向量中的值都严格为正
def msets(L, N):
if L == N:
yield (1,) * L
elif N == 1:
yield (L,)
elif N > 0:
for i in range(L - N + 1):
for m in msets(L - i - 1, N - 1):
yield (i + 1,) + m
<> >不幸,
if size
行中立即进行删减。这仍然是O(1)
每个转换;)不完全是O(1),因为构建该集可能更昂贵。@user2357112:是的,当然,但您可以使用位掩码来代替O(1)
至少为合理的符号集大小设置操作(我在这里假设符号集足够小,算法可以在合理的时间内完成)。元组前缀从未实际生成,尽管我可能不理解。假设我们的大小为1,todo=(3,)。这将尝试所有N个符号,以发现只有3个有效。对我来说,这听起来不像O(1)。这听起来像O(N)。因此,我将把复杂性放在O(N^N),类似于我的示例解决方案。抱歉,如果我理解缓慢,我缺少了什么?我可能缺少了一些东西,但为什么len(list(msets(5,3)))=6
?@Niklas:你认为它会是什么?有六种可能的长度为5的元素的多集(0,1,2)这里至少有一个问题,但是C++代码对于一个算法问题来说是足够清楚的,但是我可以在上午写Bython等价物,BTW,你的函数本质上是代码>(元组(xLangar(n)))itertools中y的+y。带替换的组合(X范围(N),L-N))
def msets(L, N):
if L == N:
yield (1,) * L
elif N == 1:
yield (L,)
elif N > 0:
for i in range(L - N + 1):
for m in msets(L - i - 1, N - 1):
yield (i + 1,) + m