题目
题目来源:力扣(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]]
思路分析
以数组 [1, 2, 3] 的全排列为例。
先写以 1 开头的全排列,它们是:[1, 2, 3], [1, 3, 2],即 1 + [2, 3] 的全排列(注意:递归结构体现在这里);
再写以 2 开头的全排列,它们是:[2, 1, 3], [2, 3, 1],即 2 + [1, 3] 的全排列;
最后写以 3开头的全排列,它们是:[3, 1, 2], [3, 2, 1],即 3 + [1, 2] 的全排列。
总结搜索的方法:按顺序枚举每一位可能出现的情况,已经选择的数字在 当前 要选择的数字中不能出现。按照这种策略搜索就能够做到 不重不漏。这样的思路,可以用一个树形结构表示。


/*** @param {number[]} nums* @return {number[][]}*/var permute = function(nums) {// 保存结果数组,保存每个路径(排列)const result = []// 调用回溯函数,传入参数backtracking(nums, nums.length, [], [])// 返回结果数组return result// 定义回溯递归函数,传入数组,长度,节点是否被使用过的数组// used 用来标记节点是否被用过 path 用来存储路径,定义为一个栈function backtracking(nums, len, used, path){// 递归出口// 如果到达叶子节点,将路径推入结果数组,并返回if(path.length === len) {result.push([...path])return}// 遍历候选字符for(let i = 0; i < len; i++){// 使用过就下一轮循环if(!used[i]){// undefind和fasle都会进来// 这里说明这个数还没有被使用,入栈pathpath.push(nums[i])// 标记这个数被使用过了used[i] = true// 开始进行递归backtracking(nums, len, used, path)// 回溯【状态重置】撤销之前的操作path.pop()used[i] = false}}}};
