【LeetCode】每日一题 全排列

56 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

46. 全排列

给定一个不含重复数字的数组 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;
        }
    }
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;