46.全排列 python

题目

题目描述

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

提示:

1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同

题解

给定一个不含重复数字的数组 nums,要求返回其所有可能的全排列。这是一个经典的回溯算法问题。回溯算法是一种通过构建所有可能的解决方案并逐个检查是否满足条件来解决问题的方法。

解决方案:回溯算法

思路:

  1. 选择列表:初始时,选择列表为输入的数组 nums
  2. 路径:记录当前构建的排列。
  3. 结束条件:当路径的长度等于 nums 的长度时,说明找到了一个完整的排列。
  4. 递归:在每次递归调用中,尝试将每个未使用的数字添加到当前路径,并继续探索后续的选择。
  5. 撤销选择:当从递归调用返回时,需要撤销上一步的选择,以便尝试其他可能性。

Python 实现:

def permute(nums):
    def backtrack(start=0):
        # 结束条件:如果起始位置等于数组长度,则找到了一个排列
        if start == len(nums):
            result.append(nums[:])
            return
        
        for i in range(start, len(nums)):
            # 交换当前元素与起始位置的元素
            nums[start], nums[i] = nums[i], nums[start]
            # 继续构建下一个位置的排列
            backtrack(start + 1)
            # 撤销选择
            nums[start], nums[i] = nums[i], nums[start]

    result = []
    backtrack()
    return result

复杂度分析:

  • 时间复杂度:O(n!),其中 n 是数组 nums 的长度。因为生成所有排列的数量是 n!。
  • 空间复杂度:O(n!),用于存储所有的排列结果。递归栈的空间复杂度是 O(n),但这不是主要因素,因为排列结果占用的空间远大于递归栈。

这个实现方法利用了回溯的思想,通过交换元素的位置来构建所有可能的排列,并且确保了不会产生重复的排列(因为题目保证了 nums 中没有重复数字)。这种方法简单直观,易于理解和实现。

提交结果

在这里插入图片描述

### Python 实现全排列算法示例 以下是几种常见的实现方式及其代码示例: #### 方法一:递归法 递归是一种简单而优雅的方式,用于生成给定列表的所有全排列。 ```python def perm(l): if len(l) <= 1: return [l] r = [] for i in range(len(l)): s = l[:i] + l[i+1:] p = perm(s) for x in p: r.append([l[i]] + x) return r ``` 上述代码通过递归调用 `perm` 函数来逐步减少输入列表长度并构建最终的结果集合[^1]。 --- #### 方法二:回溯法 回溯法利用深度优先搜索的思想,在每次决策时尝试所有可能的选择,并在不满足条件时撤销当前选择以继续探索其他路径。 ```python class Solution: def permute(self, nums: list[int]) -> list[list[int]]: def backtrack(start=0): if start == len(nums): result.append(nums[:]) return for i in range(start, len(nums)): nums[start], nums[i] = nums[i], nums[start] backtrack(start + 1) nums[start], nums[i] = nums[i], nums[start] result = [] backtrack() return result ``` 此方法的核心在于交换元素位置并通过递归来完成整个过程。它避免了显式的拷贝操作,从而提高了效率[^2]。 --- #### 方法三:字典序算法 字典序算法可以按特定顺序依次生成下一个排列组合,适合于需要连续输出多个排列的情况。 虽然该方法较难理解,但它具有较高的性能优势,尤其是在处理大规模数据集时表现出色。 ```python from typing import List def next_permutation(nums: List[int]): n = len(nums) k = -1 for i in range(n-2, -1, -1): if nums[i] < nums[i+1]: k = i break if k == -1: nums.reverse() return False l = -1 for j in range(n-1, k, -1): if nums[j] > nums[k]: l = j break nums[k], nums[l] = nums[l], nums[k] nums[k+1:] = reversed(nums[k+1:]) return True def generate_all_permutations(nums: List[int]): results = [nums[:]] while next_permutation(nums): results.append(nums[:]) return results ``` 这段代码实现了基于字典序的全排列生成器[^4]。 --- #### 方法四:内置库函数 Python 的标准库提供了非常方便的功能可以直接用来解决此类问题。 ```python import itertools L = [1, 2, 3] permutations = list(itertools.permutations(L)) print(permutations) ``` 这里借助了 `itertools.permutations()` 来快速获得目标序列的所有排列形式[^3]。 --- ### 总结 以上介绍了四种不同的实现方案——递归法、回溯法、字典序算法以及使用内置库函数的方法。每一种都有其适用场景和特点,开发者可以根据实际需求选取最适合的一种。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gxls2024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值