题目
给定一个不含重复数字的数组 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 中的所有整数 互不相同
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目解析
这是第三次写全排列了吧,每一次都以为自己会了。看了解析再写和自己一行行思考是完全不一样的,一想就是一个半小时,这大概就是真的会了吧。
Q1:需要想清楚,dfs的终止条件是什么?
A:加入输入是3个数,那么终止条件为我找全了3个数,就可以保存了。
Q2:如何知道一个数字有没有取过?
A:每个数字只能出现一遍,因此用一个访问数组vis记录每个数字是否访问过。如果输入为3个数,那么vis = [0, 0, 0]表示这三个数都没有访问过,如果访问了标记为0.
Q3:如何开始搜索
A:遍历每一个数,看看是否用过,用过的数就不再用了,继续查看下一个数。当找到没用过的数时,进入下一步dfs继续对下一个位置进行搜索。
Q4:如何进行回溯
A:每个位置dfs结束后,需要退还用过的数值,恢复vis[]标记到0
Q5:困扰的变量联动?
A:当res变量被修改时,resAll变量的值会随之修改,这里的解决方法是用切片,resAll.append(res[:]),将res的所有值切片取出来存入resAll,就可以了,当然也可以用别的方法,比如说copy,这里切片可能对初学者更友好。
本地编译器写的代码
nums = [1, 2, 3]
n = len(nums)
resAll = []
vis = [0 for i in range(n + 1)]
def dfs(step, res):
global resAll
if step > n:
resAll.append(res[:])
return
# 继续搜索
for i in range(n): # 0, 1, 2
if vis[i] == 0:
vis[i] = 1
res.append(nums[i])
dfs(step + 1, res)
res.pop()
vis[i] = 0
res = []
dfs(1, res)
print(resAll)
力扣提交的代码
力扣里面的变量不需要全局变量申明,可以直接使用。其他和本地的代码没有什么区别啦!
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
resAll = []
vis = [0 for i in range(n + 1)]
def dfs(step, res):
if step > n:
resAll.append(res[:])
return
# 继续搜索
for i in range(n): # 0, 1, 2
if vis[i] == 0:
vis[i] = 1
res.append(nums[i])
dfs(step + 1, res)
res.pop()
vis[i] = 0
res = []
dfs(1, res)
return resAll