🌈【LeetCode.31 组合总数】- JavaScript =>DFS+剪枝

410 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题目描述

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

示例 1:

输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]

思路:DFS

结束条件

  • 当递归的数组都被递归完了
  • 当路径内的元素总和 > 目标值,
  • 当路径内的元素总和 > 目标值,把路径扔到结果数组里

如果都没有到出递归的条件,就循环当前的数组,每次都进入 dfs,拼新的数组(数组的内容是从当前循环的 i 开始,直到数组结束)并传入,并拼接新的 path

var combinationSum = function(candidates, target) {
  const res = []

  function dfs (arr, path) {
    if (arr.length === 0) {
      return
    }
    const currAdd = path.reduce((curr, add) => curr + add, 0)
    if (currAdd > target) {
      return
    }
    if (currAdd === target) {
      res.push(path)
    }
    
    for (let i = 0; i < arr.length; i++) {
      dfs(arr.slice(i, arr.length), [...path, arr[i]]) 
      // 拼接新的 arr, i - arr.length 是为了把已经选过的 arr 的值排除掉。 拼接新的 path
    }
  }

  dfs(candidates, [], 0)

  return res
};

优化:DFS+剪枝

var combinationSum = function (candidates, target) {
    var resultList = [];
    var combin = function (value, path) {
        if (value === 0) return resultList.push(path.slice());

        if (value < 0) return;

        for (var i = 0; i < candidates.length; i++) {
            if (path.length === 0 || (path.length > 0 && path[path.length - 1] >= candidates[i])) {
                var minus = value - candidates[i];
                path.push(candidates[i]);
                combin(minus, path);
                path.pop(candidates[i]);
            }
        }
    };

    combin(target, []);
    return resultList;
};

总结:加了剪枝,性能上提升不少呀。


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤