LeetCode-46.全排列

haiweilian2021-03-06算法LeetCode

题目描述

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例 1:

输入: [1,2,3]
输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

解法一递归、回溯

最重要的理解两个概念,一个是递归的递和归的过程,一个是回溯的思想。

递归:递归的过程中形成一个系统栈,分为的过程, 函数调用之前的代码是的过程执行的,函数调用之后的代码是的过程执行的。

回溯:如执行时形成一个路径,当不能满足条件的时候再一步一步的回退回去 做操作 -> 递归 -> 撤销操作

先看一下树形结构,此图来自 题解open in new window

题解

上图描述了一个递归的过程和回溯的过程,在每次遍历的时候,找到一个不重复的值,然后继续递归直到条件结束,然后在归的过程中回溯到上次值,再次查找不同的值。

举例 [1, 2, 3] 现在需要遍历每一个元素,每遍历一个元素如果没有就收集起来(temp = [])就递归继续查找。

  1. 第一层递归的循环;i = 0, temp = [1] 往下递归;此时还有 i = 1、i = 2 未执行。
  2. 第二层递归的循环:1 已经存在跳过本次继续 i = 1, temp = [1, 2] 往下递归;此时还有 i = 2 未执行。
  3. 第三层递归的循环:1、2 已经存在跳过本次继续 i = 2, temp = [1, 2, 3] 往下递归;此时没有可执行。
  4. 第四层递归:每次递归开始判断了数量是否足够,这里已经完成了一个组合 [1, 2, 3] 收集起来直接返回,循环就不执行了。开始了归 + 回溯的过程。
  5. 第三层递归的回溯:撤回一步 temp = [1, 2],没有循环完成。
  6. 第二层递归的回溯里的循环:撤回一步 temp = [1],此时 i = 2 还可以继续执行。i = 2, temp = [1, 3] 往下递归;此时没有可执行。
    • 第一层递归的循环:1 已经存在跳过本次继续 i = 1, temp = [1, 3, 2] 往下递归。
    • 第一层递归:又得到了一个组合 [1, 3, 2] 收集起来直接返回。开始了归 + 回溯的过程。
    • 第一层递归的回溯:撤回一步 temp = [1, 3],没有循环完成。
  7. 第二层递归的回溯:撤回一步 temp = [1],没有循环完成。
  8. 第一层递归的回溯:撤回一步 temp = [],此时还有 i = 1、i = 2 可执行。
  9. 以下逻辑就会按照以上逻辑再走两遍。
  10. ...

代码实现

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function (nums) {
  let list = []; // 结果集合
  let temp = []; // 临时集合
  let flag = 0;

  function backtrack() {
    flag++;

    // 当排完一个组合,收集结果。开始 归 的过程。
    if (temp.length === nums.length) {
      return list.push([...temp]);
    }

    for (let i = 0; i < nums.length; i++) {
      // 如果已经存在了,下一次循环跳过
      if (temp.includes(nums[i])) continue;

      // 收集元素
      temp.push(nums[i]);
      console.log(`递-${flag}-${i}`, temp);

      backtrack(temp);

      // 回溯的过程:删除一个回到上次,对应 push 操作。
      temp.pop();
      console.log(`归-${flag}-${i}`, temp);
    }
  }

  backtrack();

  return list;
};

// ===================================================================
// ========================== @test ==================================
// ===================================================================
console.log(permute([1, 2, 3]));
// [
//   [ 1, 2, 3 ],
//   [ 1, 3, 2 ],
//   [ 2, 1, 3 ],
//   [ 2, 3, 1 ],
//   [ 3, 1, 2 ],
//   [ 3, 2, 1 ]
// ]
最后更新时间 1/13/2024, 4:55:28 AM