如何生成列表的所有排列?
如何生成列表的所有排列? 例如:
permutations([])
[]
permutations([1])
[1]
permutations([1, 2])
[1, 2]
[2, 1]
permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
How do I generate all the permutations of a list? For example:
permutations([])
[]
permutations([1])
[1]
permutations([1, 2])
[1, 2]
[2, 1]
permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
递归之美:
The beauty of recursion:
另一种方法(没有库)
输入可以是字符串或列表
ANOTHER APPROACH (without libs)
Input can be a string or a list
这是初始排序后生成排列的渐近最优方式 O(n*n!)。
有n个! 最多排列,hasNextPermutation(..) 的运行时间复杂度为 O(n)
分 3 步,
This is the asymptotically optimal way O(n*n!) of generating permutations after initial sorting.
There are n! permutations at most and hasNextPermutation(..) runs in O(n) time complexity
In 3 steps,
无论如何,我们可以使用 sympy 库,也支持多集排列
答案深受 获取 numpy 数组的所有排列
Anyway we could use sympy library , also support for multiset permutations
Answer is highly inspired by Get all permutations of a numpy array
另一个解决方案:
Another solution:
为了节省大家可能的搜索和实验时间,这里是 Python 中的非递归排列解决方案,它也适用于 Numba(从 v. 0.41 开始):
为了给大家留下关于性能的印象:
因此,仅当您必须调用时才使用此版本它来自 njitted 函数,否则更喜欢 itertools 实现。
To save you folks possible hours of searching and experimenting, here's the non-recursive permutaions solution in Python which also works with Numba (as of v. 0.41):
To give an impression about performance:
So use this version only if you have to call it from njitted function, otherwise prefer itertools implementation.
我看到这些递归函数内部发生了很多迭代,而不是完全纯粹递归......
所以对于那些甚至无法遵守单个循环的人来说,这里有一个粗鲁的、完全不必要的完全递归解决方案
I see a lot of iteration going on inside these recursive functions, not exactly pure recursion...
so for those of you who cannot abide by even a single loop, here's a gross, totally unnecessary fully recursive solution
生成
我正在使用 python3.4 的所有可能的排列:
测试用例:
Generate all possible permutations
I'm using python3.4:
Test Cases:
这是一种在列表上运行的算法,无需创建新的中间列表,类似于 https://stackoverflow.com/a/108651 中 Ber 的解决方案/184528。
您可以在这里亲自尝试代码:http://repl.it/J9v
Here is an algorithm that works on a list without creating new intermediate lists similar to Ber's solution at https://stackoverflow.com/a/108651/184528.
You can try the code out for yourself here: http://repl.it/J9v
该算法是最有效的一种,它避免了递归调用中的数组传递和操作,适用于 Python 2、3:
用法:
This algorithm is the most effective one, it avoids of array passing and manipulation in recursive calls, works in Python 2, 3:
Usage:
如果你不想使用内置方法,例如:
你可以自己实现 permute 函数
If you don't want to use the builtin methods such as:
you can implement permute function yourself
免责声明:软件包作者无耻的插件。 :)
trotter 包与大多数实现不同,因为它生成的伪列表实际上并不包含排列,而是描述排列与排序中相应位置之间的映射,从而可以处理非常大的排列“列表”,如 这个演示,它在“包含”字母表中字母的所有排列的伪列表中执行非常即时的操作和查找,而不使用比典型网络更多的内存或处理页。
无论如何,要生成排列列表,我们可以执行以下操作。
输出:
Disclaimer: shameless plug by package author. :)
The trotter package is different from most implementations in that it generates pseudo lists that don't actually contain permutations but rather describe mappings between permutations and respective positions in an ordering, making it possible to work with very large 'lists' of permutations, as shown in this demo which performs pretty instantaneous operations and look-ups in a pseudo-list 'containing' all the permutations of the letters in the alphabet, without using more memory or processing than a typical web page.
In any case, to generate a list of permutations, we can do the following.
Output:
为了性能,受 Knuth 启发的 numpy 解决方案,( p22) :
复制大块内存可以节省时间 -
它比 list(itertools.permutations(range(n)) 快 20 倍:
For performance, a numpy solution inspired by Knuth, (p22) :
Copying large blocs of memory saves time -
it's 20x faster than
list(itertools.permutations(range(n))
:这是受到使用列表理解的 Haskell 实现的启发:
This is inspired by the Haskell implementation using list comprehension:
人们确实可以迭代每个排列的第一个元素,就像 tzwenn 的答案一样。 然而,以这种方式编写此解决方案的效率更高:
此解决方案的速度大约快 30%,这显然要归功于以
len(elements) <= 1
结束的递归,而不是0< /代码>。
它的内存效率也更高,因为它使用生成器函数(通过
yield
),就像 Riccardo Reyes 的解决方案一样。One can indeed iterate over the first element of each permutation, as in tzwenn's answer. It is however more efficient to write this solution this way:
This solution is about 30 % faster, apparently thanks to the recursion ending at
len(elements) <= 1
instead of0
.It is also much more memory-efficient, as it uses a generator function (through
yield
), like in Riccardo Reyes's solution.请注意,该算法的时间复杂度为
n 阶乘
,其中n
是输入列表的长度打印运行结果:
示例:
输出:
Note that this algorithm has an
n factorial
time complexity, wheren
is the length of the input listPrint the results on the run:
Example:
Output:
功能性风格
结果:
In a functional style
The result:
常规实现(无yield - 将在内存中执行所有操作):
yield 实现:
基本思想是遍历数组中第一个位置的所有元素,然后在第二个位置遍历所有其余元素,而无需选择第一个元素,等等。您可以使用递归来执行此操作,其中停止条件是获取包含 1 个元素的数组 - 在这种情况下您将返回该数组。
Regular implementation (no yield - will do everything in memory):
Yield implementation:
The basic idea is to go over all the elements in the array for the 1st position, and then in 2nd position go over all the rest of the elements without the chosen element for the 1st, etc. You can do this with recursion, where the stop criteria is getting to an array of 1 element - in which case you return that array.
该解决方案实现了一个生成器,以避免将所有排列保存在内存中:
This solution implements a generator, to avoid holding all the permutations on memory:
称为:
called as:
输出:
当我交换列表的内容时,需要一个可变序列类型作为输入。 例如,
perm(list("ball"))
可以工作,而perm("ball")
则不行,因为您无法更改字符串。此 Python 实现的灵感来自于 Horowitz、Sahni 和 Rajasekeran 所著的《Computer Algorithms》一书中提出的算法。
Output:
As I'm swapping the content of the list it's required a mutable sequence type as input. E.g.
perm(list("ball"))
will work andperm("ball")
won't because you can't change a string.This Python implementation is inspired by the algorithm presented in the book Computer Algorithms by Horowitz, Sahni and Rajasekeran.
对于 Python 2.6 及以上:
这将作为生成器返回。 使用
list(permutations(xs))
以列表形式返回。For Python 2.6 onwards:
This returns as a generator. Use
list(permutations(xs))
to return as a list.首先,导入 itertools:
排列(顺序很重要):
组合(顺序无关紧要):
笛卡尔积(具有多个可迭代对象):
笛卡尔积(具有一个可迭代对象及其自身):
First, import
itertools
:Permutation (order matters):
Combination (order does NOT matter):
Cartesian product (with several iterables):
Cartesian product (with one iterable and itself):
使用
itertools.permutations
标准库:改编自此处演示了
itertools.permutations
可能会被实现:itertools.permutations
的文档中列出了几种替代方法。 这是一个:另一个基于
itertools.product
:Use
itertools.permutations
from the standard library:Adapted from here is a demonstration of how
itertools.permutations
might be implemented:A couple of alternative approaches are listed in the documentation of
itertools.permutations
. Here's one:And another, based on
itertools.product
:我使用了基于阶乘数字系统的算法 - 对于长度为 n 的列表,您可以组合每个排列逐项进行,从每个阶段留下的项目中进行选择。 第一项有 n 个选择,第二项有 n-1 个选择,最后一项只有一个选择,因此可以使用阶乘系统中数字的数字作为索引。 这样,数字 0 到 n!-1 对应于字典顺序中所有可能的排列。
输出:
此方法是非递归的,但在我的计算机上稍微慢一些,并且当 n! 时 xrange 会引发错误 太大而无法转换为 C 长整数(对我来说 n=13)。 当我需要它时它就足够了,但它远不是 itertools.permutations 。
I used an algorithm based on the factorial number system- For a list of length n, you can assemble each permutation item by item, selecting from the items left at each stage. You have n choices for the first item, n-1 for the second, and only one for the last, so you can use the digits of a number in the factorial number system as the indices. This way the numbers 0 through n!-1 correspond to all possible permutations in lexicographic order.
output:
This method is non-recursive, but it is slightly slower on my computer and xrange raises an error when n! is too large to be converted to a C long integer (n=13 for me). It was enough when I needed it, but it's no itertools.permutations by a long shot.
在我看来,一个非常明显的方式也可能是:
A quite obvious way in my opinion might be also:
输出:
Output:
以下代码是给定列表的就地排列,作为生成器实现。 由于它只返回对列表的引用,因此不应在生成器之外修改列表。
该解决方案是非递归的,因此使用的内存较少。 也可以很好地处理输入列表中元素的多个副本。
The following code is an in-place permutation of a given list, implemented as a generator. Since it only returns references to the list, the list should not be modified outside the generator.
The solution is non-recursive, so uses low memory. Work well also with multiple copies of elements in the input list.