如何生成列表的所有排列?例如:
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]
如何生成列表的所有排列?例如:
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]
当前回答
对于Python 2.6及以上版本:
import itertools
itertools.permutations([1, 2, 3])
这将作为生成器返回。使用列表(排列(xs))作为列表返回。
其他回答
以下代码是给定列表的就地排列,作为生成器实现。由于它只返回对列表的引用,因此不应在生成器外部修改列表。该解决方案是非递归的,因此使用了低内存。还可以很好地处理输入列表中元素的多个副本。
def permute_in_place(a):
a.sort()
yield list(a)
if len(a) <= 1:
return
first = 0
last = len(a)
while 1:
i = last - 1
while 1:
i = i - 1
if a[i] < a[i+1]:
j = last - 1
while not (a[i] < a[j]):
j = j - 1
a[i], a[j] = a[j], a[i] # swap the values
r = a[i+1:last]
r.reverse()
a[i+1:last] = r
yield list(a)
break
if i == first:
a.reverse()
return
if __name__ == '__main__':
for n in range(5):
for a in permute_in_place(range(1, n+1)):
print a
print
for a in permute_in_place([0, 0, 1, 1, 1]):
print a
print
我使用了一种基于阶乘数系统的算法——对于长度为n的列表,您可以逐项组装每个排列,从每个阶段留下的项目中进行选择。第一项有n个选项,第二项有n-1个选项,最后一项只有一个选项,因此可以使用阶乘数系统中数字的数字作为索引。这是数字0到n-1对应于词典顺序中的所有可能的排列。
from math import factorial
def permutations(l):
permutations=[]
length=len(l)
for x in xrange(factorial(length)):
available=list(l)
newPermutation=[]
for radix in xrange(length, 0, -1):
placeValue=factorial(radix-1)
index=x/placeValue
newPermutation.append(available.pop(index))
x-=index*placeValue
permutations.append(newPermutation)
return permutations
permutations(range(3))
输出:
[[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
此方法是非递归的,但在我的计算机上速度稍慢,xrange在n!太大,无法转换为C长整数(我的n=13)。当我需要它的时候,它已经足够了,但它远没有itertools.permutations。
from typing import List
import time, random
def measure_time(func):
def wrapper_time(*args, **kwargs):
start_time = time.perf_counter()
res = func(*args, **kwargs)
end_time = time.perf_counter()
return res, end_time - start_time
return wrapper_time
class Solution:
def permute(self, nums: List[int], method: int = 1) -> List[List[int]]:
perms = []
perm = []
if method == 1:
_, time_perm = self._permute_recur(nums, 0, len(nums) - 1, perms)
elif method == 2:
_, time_perm = self._permute_recur_agian(nums, perm, perms)
print(perm)
return perms, time_perm
@measure_time
def _permute_recur(self, nums: List[int], l: int, r: int, perms: List[List[int]]):
# base case
if l == r:
perms.append(nums.copy())
for i in range(l, r + 1):
nums[l], nums[i] = nums[i], nums[l]
self._permute_recur(nums, l + 1, r , perms)
nums[l], nums[i] = nums[i], nums[l]
@measure_time
def _permute_recur_agian(self, nums: List[int], perm: List[int], perms_list: List[List[int]]):
"""
The idea is similar to nestedForLoops visualized as a recursion tree.
"""
if nums:
for i in range(len(nums)):
# perm.append(nums[i]) mistake, perm will be filled with all nums's elements.
# Method1 perm_copy = copy.deepcopy(perm)
# Method2 add in the parameter list using + (not in place)
# caveat: list.append is in-place , which is useful for operating on global element perms_list
# Note that:
# perms_list pass by reference. shallow copy
# perm + [nums[i]] pass by value instead of reference.
self._permute_recur_agian(nums[:i] + nums[i+1:], perm + [nums[i]], perms_list)
else:
# Arrive at the last loop, i.e. leaf of the recursion tree.
perms_list.append(perm)
if __name__ == "__main__":
array = [random.randint(-10, 10) for _ in range(3)]
sol = Solution()
# perms, time_perm = sol.permute(array, 1)
perms2, time_perm2 = sol.permute(array, 2)
print(perms2)
# print(perms, perms2)
# print(time_perm, time_perm2)
```
如果用户希望在列表中保留所有排列,可以使用以下代码:
def get_permutations(nums, p_list=[], temp_items=[]):
if not nums:
return
elif len(nums) == 1:
new_items = temp_items+[nums[0]]
p_list.append(new_items)
return
else:
for i in range(len(nums)):
temp_nums = nums[:i]+nums[i+1:]
new_temp_items = temp_items + [nums[i]]
get_permutations(temp_nums, p_list, new_temp_items)
nums = [1,2,3]
p_list = []
get_permutations(nums, p_list)
如果不想使用内置方法,例如:
import itertools
list(itertools.permutations([1, 2, 3]))
你可以自己实现permute函数
from collections.abc import Iterable
def permute(iterable: Iterable[str]) -> set[str]:
perms = set()
if len(iterable) == 1:
return {*iterable}
for index, char in enumerate(iterable):
perms.update([char + perm for perm in permute(iterable[:index] + iterable[index + 1:])])
return perms
if __name__ == '__main__':
print(permute('abc'))
# {'bca', 'abc', 'cab', 'acb', 'cba', 'bac'}
print(permute(['1', '2', '3']))
# {'123', '312', '132', '321', '213', '231'}