算法|回溯套路

回溯套路

求子集

初始化
---sets
---subset
---backTrack
--- funtion backTrack
    直接存入sets
    终止条件
    for 从i开始
        存入subset
        backTrack
        subset弹出pop
var subsets = function (nums) {
  // 1. 初始化总集合 ,子集合
  const sets = [];
  let subsets = [];
  // 2. 调用递归
  backTrack(0, subsets);
  // 3. 定义递归
  function backTrack(start, subsets) {
    // 每一次递归之前将子集放入总集里, 注意这里的解构
    sets.push([...subsets]);
    // 终止条件
    if (start >= nums.length) return;
    //
    for (let j = start; j < nums.length; j++) {
      // 将本次递归的元素加入子集
      subsets.push(nums[j]);
      backTrack(j + 1, subsets);
      //   回溯的根本: 递归的尽头, 开始把子集开始往回退
      subsets.pop();
    }
  }
  // 返回结果
  return sets;
};
console.log(subsets([1, 2, 3]));
// [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]];

求排列 (多了 used 的限制条件)

初始化
---sets
---subset
---used (新增)
---backTrack
--- funtion backTrack
    长度相等 存入sets
    终止条件
    for 从0开始
        未使用
        存入subset
        used[j]=1
        backTrack
        used[j]=0
        subset弹出pop
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function (nums) {
  const sets = [];
  let subsets = [];
  //   新增used逻辑
  const used = Array(nums.length).fill(0);
  backTrack(nums, subsets, sets);
  //   全排列是通过参数used来判断是否进入下一轮递归, 而不是原始i的坐标了, 切记
  function backTrack(nums, subsets, sets) {
    if (subsets.length === nums.length) {
      sets.push([...subsets]);
      return;
    }
    for (let j = 0; j < nums.length; j++) {
      if (used[j] === 0) {
        subsets.push(nums[j]);
        used[j] = 1;
        backTrack(nums, subsets, sets);
        used[j] = 0;
        subsets.pop();
      }
    }
  }
  return sets.length;
};
console.log(permute([1, 2, 3])); //6

求组合 (子集组合等于某值)

初始化
---sets
---subset
---backTrack
--- funtion backTrack
    直接存入sets
    终止条件
    for 从start开始
        存入subset
        backTrack (剩余目标值target-cur[j])
        subset弹出pop
/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function (candidates, target) {
  const sets = [];
  const subsets = [];
  const len = candidates.length;
  backTrack(0, target, subsets);
  function backTrack(start, target, subsets) {
    // 中止条件
    if (target < 0) return;
    if (target === 0) {
      sets.push([...subsets]);
      return;
    }
    // 遍历+递归
    for (let j = start; j < len; j++) {
      subsets.push(candidates[j]);
      backTrack(j, target - candidates[j], subsets);
      subsets.pop();
    }
  }
  return sets;
};
console.log(combinationSum([2, 3, 6, 7], 7)); // [ [ 2, 2, 3 ], [ 7 ] ]
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值