本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
输入: nums = [1,2,3]
输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
题目解析
思路一
我们这里使用递归进行实现,首先声明三个数组,分别是当前的路径,路径是否已经经过,和最后的结果数组。在使用递归,结束条件是当前路径数组的长度等于给定nums数组的长度,进入递归后,遍历nums数组,如果遍历到没有通过的数字,就放入路径数组,并把该数字标为已用,然后进入递归。在退出时将该数组从track中弹出,并标为未用,需要注意的是,在将track放入res时,因为是数组中放数组,数组中放引用类型需要特别注意放入一个又新地址的track副本,可以用Array.from或者concat,最后进行返回
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
var track = [];
var used = new Array(nums.length).fill(false);
var res = [];
var backtrack = function(nums, track, used){
if(track.length === nums.length){
let item = track.concat();
res.push(item);
return;
}
for(let i = 0; i < nums.length; i++){
if(used[i]){
continue;
}
track.push(nums[i]);
used[i] = true;
backtrack(nums, track, used);
track.pop();
used[i] = false;
}
}
backtrack(nums, track, used);
return res;
};
思路二
我们这里采用递归方式,每轮递归进行两次循环。记下初始的上一次结果preResult为[[]],结合初始数组nums,每次递归内,创建一个新数组res,对preResult和nums执行两个循环,将结果放入res。再递归的把res作为下一次的preResult传入permute(nums,res)。终止条件为判断到preResult中任何一个元素长度等于nums的长度。此时得到每轮的res是对于nums的重复排列,需要额外循环体内需做一个重复判断,最后得到的便是题目中的非重复的全排列了
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums,preResult=[[]]) {
if(preResult[0].length===nums.length)return preResult
const res=[]
for(let i=0;i<preResult.length;i++){
for(let j=0;j<nums.length;j++){
if(!preResult[i].includes(nums[j])){
res.push([...preResult[i],nums[j]])
}
}
}
return permute(nums,res)
};