携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
给定一个不含重复数字的数组 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 中的所有整数 互不相同
解题思路
// 第一种
回溯法;
注意JS中引用类型,浅拷贝和深拷贝;
被访问过的把 visited[i] = true;
递归结束或者找到结果之后,再把对应得 visited[i] = false;
// 第二种
插入法
// 第三种
准备path数组,存放每一个回溯递归的分支中的数字排列,调用回溯函数 传入nums,nums长度,used数组,used表示已经使用的数字,回溯函数中循环nums中的数,每层循环将nums中的元素加入path中,然后递归调用回溯函数,调用完成之后,回溯之前的状态,当path数组的长度和nums的长度相同就找到了一种排列
代码实现
// 第一种
var permute = function(nums){
let result = [];
findSon([],[]);
function findSon(visited,item){
for(let j = 0; j < nums.length; j++){
if(!visited[j]){
visited[j] = true;
item.push(nums[j]);
if(item.length == nums.length){
let newItem = JSON.stringify(item);
newItem = JSON.parse(newItem)
result.push(newItem);
visited[j] = false;
item.pop();
}else{
findSon(visited, item);
visited[j] = false;
item.pop();
}
}
}
}
return result;
};
// 第二种
const permute = (nums) => {
let result = [
[nums[0]]
],
j = undefined,
arr = []
for (let i = 1; i < nums.length; i++) { // 不断插入新的排列数
arr = [] // 将临时变量置空
result.forEach((value) => {
value.push(nums[i]) // 对上一次的全排列都插入新的排列数
// arr.push(JSON.parse(JSON.stringify(value)))
arr.push([...value])
j = value.length - 1
while (j > 0) { // 将新排列数插入到不同位置
[value[j - 1], value[j]] = [value[j], value[j - 1]]
// arr.push(JSON.parse(JSON.stringify(value)))
arr.push([...value])
j--
}
})
result = arr
}
return result
}
// 第三种
var permute = function(nums) {
const res = [], path = [];
backtracking(nums, nums.length, []);//调用回溯函数 传入nums,nums长度,used数组
return res;
function backtracking(n, k, used) {
if(path.length === k) {//递归终止条件
res.push(Array.from(path));
return;
}
for (let i = 0; i < k; i++ ) {
if(used[i]) continue;//已经使用过了就跳过本轮循环
path.push(n[i]);
used[i] = true;
backtracking(n, k, used);//递归
path.pop();//回溯 将push进的元素pop出来 然后标记成未使用 继续其他分支
used[i] = false;
}
}
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;