如何生成列表的所有排列?例如:

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]

当前回答

此解决方案实现了一个生成器,以避免在内存中保留所有排列:

def permutations (orig_list):
    if not isinstance(orig_list, list):
        orig_list = list(orig_list)

    yield orig_list

    if len(orig_list) == 1:
        return

    for n in sorted(orig_list):
        new_list = orig_list[:]
        pos = new_list.index(n)
        del(new_list[pos])
        new_list.insert(0, n)
        for resto in permutations(new_list[1:]):
            if new_list[:1] + resto <> orig_list:
                yield new_list[:1] + resto

其他回答

此解决方案实现了一个生成器,以避免在内存中保留所有排列:

def permutations (orig_list):
    if not isinstance(orig_list, list):
        orig_list = list(orig_list)

    yield orig_list

    if len(orig_list) == 1:
        return

    for n in sorted(orig_list):
        new_list = orig_list[:]
        pos = new_list.index(n)
        del(new_list[pos])
        new_list.insert(0, n)
        for resto in permutations(new_list[1:]):
            if new_list[:1] + resto <> orig_list:
                yield new_list[:1] + resto

这是受Haskell实现使用列表理解的启发:

def permutation(list):
    if len(list) == 0:
        return [[]]
    else:
        return [[x] + ys for x in list for ys in permutation(delete(list, x))]

def delete(list, item):
    lc = list[:]
    lc.remove(item)
    return lc
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)
```

用递归求解,遍历元素,取第i个元素,然后问自己:“其余项目的排列是什么”,直到没有更多的元素。

我在这里解释了解决方案:https://www.youtube.com/watch?v=_7GE7psS2b4

class Solution:
    def permute(self,nums:List[int])->List[List[int]]:
        res=[]
        def dfs(nums,path):
            if len(nums)==0:
                res.append(path)
            for i in range(len(nums)):
                dfs(nums[:i]+nums[i+1:],path+[nums[i]])
        dfs(nums,[])
        return res

该算法是最有效的算法,它避免了递归调用中的数组传递和操作,适用于Python 2、3:

def permute(items):
    length = len(items)
    def inner(ix=[]):
        do_yield = len(ix) == length - 1
        for i in range(0, length):
            if i in ix: #avoid duplicates
                continue
            if do_yield:
                yield tuple([items[y] for y in ix + [i]])
            else:
                for p in inner(ix + [i]):
                    yield p
    return inner()

用法:

for p in permute((1,2,3)):
    print(p)

(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)