这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给定一个不含重复数字的数组 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]]
链接:leetcode-cn.com/problems/pe…
题解
这道题是一道典型的dfs+回溯模式题. 在LeetCode 数组类型题目做前必看文中, 有个排列dfs的模版, 直接套过来就可以了. 我们先直接给出代码
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
const n = nums.length
let used = new Array(n).fill(0)
let ans = []
const dfs = (nums, d, n, used, curr, ans) => {
if (d === n) {
ans.push([...curr])
return
}
for (let i = 0; i < n; ++i) {
if (used[i]) continue
used[i] = 1
curr.push(nums[i])
dfs(nums, d+1, n, used, curr, ans)
// 恢复原样
used[i] = 0
curr.pop()
}
}
dfs(nums, 0, n, used, [], ans)
return ans
};
代码中主要部分是 dfs 这个函数, 这个函数有几个重要的点.
一个是递归终止条件: d === n, 其中 d 代表 curr 数组的元素个数, n 代表 nums 数组的元素个数, 当 nums 所有的元素都添加到了 curr 数组中时, 就表示其中的一个排列被找到了, 然后 push 进 ans 数组中.
一个是 used 数组: used 数组被用来标记 nums[i] 是否已经被使用过了, 1 表示使用过了, 0 表示未使用过. 因为我们每次都需要从 i = 0 位置开始遍历(为了找出所有组合), 所以 used 数组必须要存在.
另外的点就是, 在一次递归dfs之后, 我们必须要将之前添加的 nums[i] 从 curr 中 pop 出去, 以及将 used[i] 置为 0, 这样做就不会影响后面的递归, 这一步称之为回溯. 也就是回到之前的状态.
对于数组 [1, 2, 3], 对该数组的求解过程可以看下图, 本图来源于 liweiwei1419
时间复杂度: 对于长度为 n 的数组, 其一共有 n! 种组合, 而求出每种组合都需要遍历一遍数组, 故时间复杂度为 O(n * n!)