回溯算法巧解全排列问题 | 创作者训练营

1,055 阅读2分钟

题目

LeetCode 46 全排列

分析

回溯算法的主要特征有两点:一是要遍历所有的情况;二是找到一种可行解后,要回退到上一步,遍历其他情况。

题目中我们第一个遍历到的可行解为:

1 -> 2 -> 3      // 满足可行解条件,回退到第二位,继续遍历第二位的其他情况
1 -> 3           // 第二位遍历到 3,不满足条件,继续往后遍历
1 -> 3 -> 2      // 第三位遍历到 2,满足条件,开始回退
2                // 第一位遍历到 2, 依次类推
2 -> 1
2 -> 1 -> 3
...
直到遍历完所有的情况

实现

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
const permute = function(nums) {
  const res = [];
  let tmp = [];
  const backTrack = (nums) => {
    //递归退出条件
    if(tmp.length == nums.length) {
      res.push([...tmp]);
      return;
    }
    
    for(let num of nums) {
      // 找到不重复的解,加入到中间变量中
      if(tmp.indexOf(num) < 0) {
        tmp.push(num);
        backTrack(nums);
        tmp.pop(num);
      }
    }
  }
  
  backTrack(nums);
  
  return res;
};

总结

回溯算法,重在「回溯」。有来有回,遍历完一种情况,需要回退到上一步。这里是理解回溯算法的关键。在代码中则表现为:回溯的前一步将子项加入到数组中,后一步又将子项移除。刚开始看着有点绕,画一下调用栈就比较容易理解。移除的过程其实是在完成一个可行解之后才调用,并不是马上就移除的。

「 一枚前端学习小透明,努力学习前端知识,同时分享自己对生活的一些思考,欢迎一起讨论交流。如果我的文章对你有帮助,请点个赞,会非常感恩你的鼓励。完」

回溯算法巧解全排列问题 | 创作者训练营 征文活动正在进行中......