生成除循环旋转之外的所有排列
因此,我需要一种算法来生成不包括循环旋转的数字列表的所有排列(例如 [1,2,3] == [2,3,1] == [3,1,2])。
当序列中至少有 1 个唯一数字时,它相当简单,取出该唯一数字,生成剩余数字的所有排列(但对“标准”排列算法进行少量修改)并将唯一数字添加到前面。
为了生成排列,我发现有必要将排列代码更改为:
def permutations(done, options)
permuts = []
seen = []
for each o in options
if o not in seen
seen.add(o)
permuts += permutations(done+o, options.remove(o))
return permuts
仅在选项中使用每个唯一数字一次意味着您不会两次获得 322。
当没有唯一元素时,该算法仍然输出旋转,例如,对于 [1,1,2,2],它将输出 [1,1,2,2]、[1,2,2,1] 和 [1,2] ,1,2],前两个是循环旋转。
那么是否有一种有效的算法可以让我生成所有排列,而不必事后删除循环旋转?
如果不是,消除循环旋转的最有效方法是什么?
注意:这不是使用Python,而是使用C++。
So I need an algorithm to generate all permutations of a list of numbers excluding cyclic rotations (e.g. [1,2,3] == [2,3,1] == [3,1,2]).
When there is at least 1 unique number in the sequence it is fairly straight forward, take out that unique number, generate all permutations of the remaining numbers (but with a small modification to the 'standard' permutations algorithm) and add the unique number to the front.
For generating the permutations I've found that it's necessary to change the permutations code to:
def permutations(done, options)
permuts = []
seen = []
for each o in options
if o not in seen
seen.add(o)
permuts += permutations(done+o, options.remove(o))
return permuts
Only using each unique number in options once means that you don't get 322 twice.
This algorithm still outputs rotations when there are no unique elements, e.g. for [1,1,2,2] it would output [1,1,2,2], [1,2,2,1] and [1,2,1,2] and the first two are cyclic rotations.
So is there an efficient algorithm that would allow me to generate all the permutations without having to go through afterwards to remove cyclic rotations?
If not, what would be the most efficient way to remove cyclic rotations?
NOTE: this is not using Python, but rather C++.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于所有数字都不同的排列情况,这很简单。假设数字是
1,2,...,n
,然后生成1,2,...,n-1
的所有排列并粘贴n
在前面。这给出了全套模循环旋转的所有排列。例如,对于n=4
,您可以执行此操作,这可确保
1,2,3,4
的每个排列的某种循环旋转在列表中恰好出现一次。对于需要多重集排列(允许重复条目)的一般情况,您可以使用类似的技巧。删除最大字母
n
的所有实例(类似于忽略上例中的4
)并生成剩余多重集的所有排列。下一步是以规范的方式将n
放回到排列中(类似于将4
放在上面示例中的开头)。这实际上只是查找所有 Lyndon 单词 来生成 项链
For the case of permutations where all numbers are distinct, this is simple. Say the numbers are
1,2,...,n
, then generate all permutations of1,2,...,n-1
and stickn
at the front. This gives all permutations of the full set modulo cyclic rotations. For example, withn=4
, you would doThis ensures that some cyclic rotation of each permutation of
1,2,3,4
appears exactly once in the list.For the general case where you want permutations of a multiset (repeated entries allowed), you can use a similar trick. Remove all instances of the largest letter
n
(similar to ignoring the4
in the above example) and generate all permutations of the remaining multiset. The next step is to put then
s back into the permutations in canonical ways (similar to putting the4
at the beginning in the above example).This is really just a case of finding all Lyndon words to generate necklaces
考虑测试您输出的每个排列,寻找“词汇上”早于您所获得的循环旋转。如果有,不要返回它 - 它会在其他地方被枚举。
选择“唯一”的第一个元素(如果存在)可以帮助您进行优化。您知道,如果您修复了第一个元素,并且它是唯一的,那么您不可能通过旋转来复制它。另一方面,如果没有这样的独特元素,则只需选择出现次数最少的元素即可。这样您只需要检查具有第一个元素的循环旋转。 (例如,当您生成 [1,2,2,1] 时 - 您只需要检查 [1,1,2,2],而不是 [2,2,1,1] 或 [2,1,1,2 ])。
好吧,伪代码......显然是 O(n!),而且我确信没有更聪明的方法,因为“所有符号不同”的情况显然必须返回 (n-1)!元素。
Think about testing each of the permutations you output, looking for a cyclic rotation that's "lexically" earlier than the one you've got. If there is one, don't return it - it will have been enumerated somewhere else.
Choosing a "unique" first element, if one exists, helps you optimize. You know if you fix the first element, and it's unique, then you can't possibly have duplicated it with a rotation. On the other hand, if there's no such unique element, just choose the one that occurs the least. That way you only need to check for cyclic rotations that have that first element. (Example, when you generate [1,2,2,1] - you only need to check [1,1,2,2], not [2,2,1,1] or [2,1,1,2]).
OK, pseudocode... clearly O(n!), and I'm convinced there's no smarter way, since the case "all symbols different" obviously has to return (n-1)! elements.
该解决方案将涉及一些
itertools.permutations
用法,set()
,和一些好的老式的设置差异。请记住,查找排列的运行时间仍然是 O(n!)。我的解决方案也不会内嵌执行此操作,但可能有一个更优雅的解决方案,允许您这样做(并且不涉及itertools.permutations
)。为此,这是完成任务的直接方法。步骤 1:使用给定的第一个元素生成循环的算法。对于列表
[1, 1, 2, 2]
,这将为我们提供[1, 1, 2, 2], [1, 2, 2, 1], [2, 1, 1, 2], [2, 2, 1, 1]
。第 2 步:导入
itertools.permutations
以首先给出排列,然后将其结果设置到set
中。第三步:使用生成器给我们自己的集合,以及循环(我们想要摆脱的东西)。
步骤 4:对每个应用设置差值并删除循环。
希望这会对您有所帮助。我愿意接受建议和/或更正。
This solution is going to involve a bit of
itertools.permutations
usage,set()
, and some good ol' fashioned set difference. Bear in mind, the runtime for finding a permutation will still be O(n!). My solution won't do it in-line, either, but there may be a much more elegant solution that allows you to do so (and doesn't involveitertools.permutations
). For this purpose, this is the straightforward way to accomplish the task.Step 1: Algorithm for generating cycles, using the first element given. For a list
[1, 1, 2, 2]
, this will give us[1, 1, 2, 2], [1, 2, 2, 1], [2, 1, 1, 2], [2, 2, 1, 1]
.Step 2: Importing
itertools.permutations
to give us the permutations in the first place, then setting up its results into aset
.Step 3: Using the generator to give us our own set, with the cycles (something we want to rid ourselves of).
Step 4: Apply set difference to each and the cycles are removed.
Hopefully this will help you out. I'm open to suggestions and/or corrections.
首先,我将展示我们将
使用
的容器和算法:接下来是我们的
向量
,它将代表排列
:我们需要一个比较对象检查排列是否是旋转:
以及
typedef
一个使用循环比较对象的set
:然后主要功能非常简单:
输出:
我还没有实现 <代码>CompareCyclicPermutationsEqual 然而。此外,您还需要实现 ostream&运算符<<(ostream&os, const Permutation& permutation)。
First I'll show the containers and algorithms we'll be
using
:Next our
vector
which will represent thePermutation
:We need a comparison object to check whether a permutation is a rotation:
And
typedef
aset
which uses the cyclic comparison object:Then the main function is quite simple:
Output:
I haven't implemented
CompareCyclicPermutationsEqual
yet. Also you'd need to implementostream& operator<<(ostream& os, const Permutation& permutation)
.