题目
分析
回溯算法的主要特征有两点:一是要遍历所有的情况;二是找到一种可行解后,要回退到上一步,遍历其他情况。
题目中我们第一个遍历到的可行解为:
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;
};
总结
回溯算法,重在「回溯」。有来有回,遍历完一种情况,需要回退到上一步。这里是理解回溯算法的关键。在代码中则表现为:回溯的前一步将子项加入到数组中,后一步又将子项移除。刚开始看着有点绕,画一下调用栈就比较容易理解。移除的过程其实是在完成一个可行解之后才调用,并不是马上就移除的。
「 一枚前端学习小透明,努力学习前端知识,同时分享自己对生活的一些思考,欢迎一起讨论交流。如果我的文章对你有帮助,请点个赞,会非常感恩你的鼓励。完」