链接
https://leetcode-cn.com/problems/permutations/
前言
中等难度的果然难,理解起来都费劲
题目
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
关键
- 递归的思想
思路1
- 动态规划
class Solution:
def permute(self, nums):
dp={}
dp[0] = [[]]
for i in range(1,len(nums)+1):
dp[i]=[]
for j in dp[i-1]:
for k in nums:
if k not in j:
tmp = j[:]
tmp.append(k)
dp[i].append(tmp[:])
return dp[len(nums)]
思路2
- 回溯法
- 交换
class Solution:
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(first = 0):
# 所有数都填完了
if first == n:
res.append(nums[:])
for i in range(first, n):
# 动态维护数组
nums[first], nums[i] = nums[i], nums[first]
# 继续递归填下一个数
backtrack(first + 1)
# 撤销操作
nums[first], nums[i] = nums[i], nums[first]
n = len(nums)
res = []
backtrack()
return res
思路3
- 调库
list(itertools.permutations(nums))
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
return list(itertools.permutations(nums))
思路4
- 见缝插数
- 三层遍历
- 第1层
i
:选nums
中的元素nums[i]
- 第2层
k
:选要被插数的子列表 - 第3层
j
:选插数的位置
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = [[nums[0]]]
n = len(nums)
tmp = []
for i in range(1, n):
for k in res:
for j in range(len(k)+1):
k.insert(j,nums[i])
tmp.append(k[:])
k.pop(j)
res = tmp
tmp = []
return res
相关知识
疑问
参考
[1] 回溯算法入门级详解 + 练习(持续更新)
[2] 四种方法:DFS、BFS、动态规划和贪心枚举
[3] 全排列
[4] 超强gif助你理解使用“4种”方法求解本题