58.组合总和

4 阅读1分钟

题目链接

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 **不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

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

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

解法 回溯剪枝

思路

先想一下递归需要哪些参数呢?每次递归的 path ,然后累加或者累减的参数,其次就是每次开始的索引。

为什么需要索引?如果传递索引,那么每次都是从 0 开始循环递归,这样会造成很多重复组合。

接下来就是递归结束条件,如果累加或累减到 target 或者 0 则放入结果集,退出递归。这里还可以稍微剪一下枝,数组里都是正数,如果当前结果不支持达成目标,那么后续的都不可能,所以也可以退出。

下面就是循环要从 start 开始,这样避免和很多重复组合,递归的时候传入当前 i 这样是为了重复选择这个数。

代码

function combinationSum(candidates: number[], target: number): number[][] {
    const result = [];

    const dfs = (path, start, rest) => {
        if (rest === 0) {
            result.push([...path]);
            return;
        }
        if (rest < 0) {
            return;
        }
        
        for (let i = start; i < candidates.length; i++) {
            path.push(candidates[i]);
            dfs(path, i, rest - candidates[i]);
            path.pop();
        }
    };

    dfs([], 0, target);
    return result;
};

时空复杂度

时间复杂度:O(2^target)

空间复杂度:O(target)