一、全排列
var permute = function(nums){ // 1. 设置结果集 const result = []; // 2. 回溯 const recursion = (path, set) => { // 2.1 设置回溯终止条件 if (path.length === nums.length) { // 2.1.1 推入结果集 result.push(path.concat()); // 2.1.2 终止递归 return; } // 2.2 遍历数组 for (let i = 0; i < nums.length; i++) { // 2.2.1 必须是不存在 set 中的坐标 if (!set.has(i)) { // 2.2.2 本地递归条件(用完记得删除) path.push(nums[i]); set.add(i); // 2.2.3 进一步递归 recursion(path, set); // 2.2.4 回溯:撤回 2.2.2 的操作 path.pop(); set.delete(i); } } }; recursion([], new Set()); // 3. 返回结果 return result;};
二、子集
const subsets = (nums) => { // 1. 设置结果集 const result = [[]]; // 2. 数组排序 nums.sort((a, b) => a - b); // 3. 递归 const recursion = (index, path) => { // 3.1 设置终止条件 if (path.length === nums.length) { return; } // 3.2 遍历数组 for (let i = index; i < nums.length; i++) { // 3.2.1 添加内容 path.push(nums[i]); // 3.2.2 添加结果集 result.push(path.concat()); // 3.2.3 进一步递归 recursion(i + 1, path); // 3.2.4 回溯,还原之前状态,以备下一次使用 path.pop(); } }; recursion(0, []); // 4. 返回结果 return result;};
三、组合
var combine = function (n, k) { const res = [] if (k <= 0 || n <= 0) return res; const track = []; const backtrack = (n, k, start, track) => { // 到达树的底部 if (k === track.length) { res.push(track.concat()); return; } // 注意i从start开始递增 for (let i = start; i <= n; i++) { // 做选择 track.push(i); backtrack(n, k, i + 1, track); // 撤销选择 track.pop(); } } backtrack(n, k, 1, track); return res;};