代码随想录算法训练营第二十七天|LeetCode39. 组合总和、LeetCode40.组合总和II、LeetCode131.分割回文串

LeetCode39. 组合总和

题目链接/文章讲解

思路:

这道题是在同一集合里寻找 所以需要一个startIndex来规定寻找范围  注意这道题的减枝操作是 控制当总和 大于目标值的return时间,可以将此步骤在循环时就决定好了 

代码实现:

 var combinationSum = function (candidates, target) {
      let result = [];
      let path = [];
      const backTracking = (candidates, target, sum, startIndex) => {
        if (sum > target) return
        if (sum === target) {
          result.push(sum)
          return
        }
        for (let i = startIndex; i < candidates.length; i++) {
          sum += candidates[i];
          path.push(candidates[i])
          backTracking(candidates, target, sum, i);
          sum -= candidates[i]
          path.pop()
        }
      }
      backTracking(candidates, target, 0, 0)
      return result
    };
    //减枝操作
    var combinationSum = function (candidates, target) {
      let result = [];
      let path = [];
      candidates.sort((a, b) => a - b)
      const backTracking = (sum, startIndex) => {
        if (sum === target) {
          result.push([...path])
          return
        }
        for (let i = startIndex; i < candidates.length; i++) {
          const n = candidates[i]
          if (n > target - sum) break
          sum += candidates[i];
          path.push(candidates[i])
          backTracking(sum, i);
          sum -= candidates[i]
          path.pop()
        }
      }
      backTracking(0, 0)
      return result
    };

LeetCode40.组合总和II

题目链接/文章讲解

思路:

有两个方法 一个使用used数组记录使用过的数字,另一个可以不使用used数组

本题的难点在于:集合(数组candidates)有重复元素,但还不能有重复的组合

  var combinationSum2 = function (candidates, target) {
      let result = [];
      let path = [];
      let sum = 0;
      const len = candidates.length;
      let used = new Array(len).fill(false);
      candidates.sort((a, b) => a - b)

      const backTracking = (startIndex) => {

        if (sum === target) {
          result.push([...path]);
          return
        }
        for (let i = startIndex; i < candidates.length; i++) {
          let cur = candidates[i]
          console.log(used)
          if (cur > target - sum || i > 0 && candidates[i - 1] === candidates[i] && used[i - 1] === false) {
            continue;
          }
          sum += candidates[i];
          used[i] = true;
          path.push(candidates[i])
          backTracking(i + 1)
          sum -= candidates[i];
          used[i] = false;
          path.pop()
        }
      }
      backTracking(0)
      return result
    };
    var combinationSum2 = function (candidates, target) {
      let result = [];
      let path = [];
      let sum = 0;
      const len = candidates.length;
      candidates.sort((a, b) => a - b)

      const backTracking = (startIndex) => {

        if (sum === target) {
          result.push([...path]);
          return
        }
        for (let i = startIndex; i < candidates.length; i++) {
          let cur = candidates[i]
          if (cur > target - sum || i > startIndex && candidates[i - 1] === candidates[i]) {
            continue;
          }
          sum += candidates[i];

          path.push(candidates[i])
          backTracking(i + 1)
          sum -= candidates[i];

          path.pop()
        }
      }
      backTracking(0)
      return result
    };

LeetCode131.分割回文串

题目链接/文章讲解

思路:

本题这涉及到两个关键问题:

  1. 切割问题,有不同的切割方式
  2. 判断回文

控制startIndex为切割线 只要startIndex的大小 大于等于数组长度 即为递归的终止条件 

代码实现

const isPalindrome = (s, l, r) => {
      for (let i = l, j = r; i < j; i++, j--) {
        if (s[i] !== s[j]) {
          return false
        }
      }
      return true

    }
    var partition = function (s) {
      const res = [], path = [], len = s.length;
      const backTracking = (startIndex) => {
        if (startIndex >= len) {
          res.push(Array.from(path));
          return
        }
        for (let i = startIndex; i < len; i++) {
          if (!isPalindrome(s, startIndex, i)) continue
          path.push(s.slice(startIndex, i + 1))
          backTracking(i + 1);
          path.pop()
        }
      }
      backTracking(0);
      return res
    };

总结

切割问题较难理解  尤其对于切割线的把握更是比较困难 需要继续努力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值