leetcode top100挑战, 每天不鸽一道题之 组合总和(18/100)

1,063 阅读2分钟

题目描述

组合总和

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

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。

解集不能包含重复的组合。

leetcode-cn.com/problems/re…


示例 1:

输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]


示例 2:

输入:candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

标签

dfs

解题分析

1. dfs

直接上讲解。

老规矩,对于列表中,要求元素与元素之间的的结果,直接dfs递归一波。
这道题看讲解说是教科书般的dfs题,来跟着思路走一下吧。

输入:candidates = [2,3,6,7], target = 7
求:能组合target的解集。
[
  [7],
  [2,2,3]
]

注意这里每个元素都可以无限用,比如上方例题答案的[2, 2, 3]中的2。

基本上就直接递归,这里说下几个点。
1. 结束递归的条件。
    (1)传入数组的长度,递归是以传入的数组的每个元素来递归,遍历完数组也就结束了。
    (2)递归传入的target等于0,这里可以看下面解说。

2. 以什么为递归的条件。
    根据题意,我们需要获取target的集,怎么获取?
    递归每个数(cur)呗,target - cur 大于0吗?不大于0,说明解集还有选择,
    继续递归,如果等于0,那就说明获得了正确的答案,如果小于0,那就是递归这条线不成立,跑路。

基本上就这样,看一个大佬画的图和代码吧。

image.png 来人上代码!!!!!

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
    const ans = []
    // target: 每根递归线中 target减去递归元素的值
    // combine: 解集
    // index: 递归的元素
    const dfs = (target, combine, index) => {
        // 数组遍历结束
        if(index === candidates.length) {
            return;
        }
        // 如果等于0,说明获得了正确的答案,把答案推了之后退出递归。
        if(target === 0) {
            ans.push(combine)
            return;
        }
        // 递归元素值,相当于遍历了传入数组,再dfs
        dfs(target, combine, index+1)
        // 如果大于等于0,说明target还能进行递归,继续冲进去!
        if(target - candidates[index] >= 0) {
            dfs(target - candidates[index], [...combine, candidates[index]], index)
        }
    }
    // 传入递归,最开始的递归传初始值
    dfs(target, [], 0)
    return ans
};

image.png

最后

从今天开始不鸽,每天一道算法题并发布文章,首先想要解决的题组为Top100,第十八道题目打完收工!!