LeetCode 39 Combination Sum (Tag:Array Difficulty:Medium)|8月更文挑战

228 阅读1分钟

前言

关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!

题目描述

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

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

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

示例 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]]

示例 3:
输入: candidates = [2], target = 1
输出: []

示例 4:
输入: candidates = [1], target = 1
输出: [[1]]

示例 5: 输入: candidates = [1], target = 2
输出: [[1,1]]

链接:leetcode-cn.com/problems/co…

题解

采用LeetCode 数组类型题目做前必看一文中, 组合dfs的模板可以解决本问题.
首先, 先看一下组合类型dfs的模板

const Combination = (nums, d, n, s, curr, ans) => {
    if (d === n) {
        ans.push([...curr])
        return
    }
    for (let i = s; i < n; ++i) {
        curr.push(nums[i])
        Combination(nums, d + 1, n, i + 1, curr, ans)
        curr.pop()
    }
}

上面的模板函数有5个参数, nums 表示完整的数组, d 表示当前 curr 数组的长度, n 表示 nums 数组的长度, s 表示当前遍历到的元素下标, curr 表示当前元素组成的子数组, ans 表示最后存放结果的数组.
模板函数的递归终止条件是当curr数组的长度和nums数组长度相同. 递归过程是 s 位置的元素开始遍历, 确保不会重复选择之前选过的数.
本题和上述组合dfs模板类似, 只有些许的不同.
首先是递归终止条件, 本题的条件是找到和为 target 的子数组, 所以递归终止条件为子数组的和等于 target.
其次, 本题可以重复选择同一个数字, 即递归过程中下一次递归还应该从 i 开始, 而不是 i + 1.
同时, 我们可以先对 candidates 数组排序, 在递归过程中当 candidates[i] > target 时, 可以提前终止递归, 相当于一个剪枝操作.
具体代码如下:

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
    candidates.sort((a, b) => a - b)
    let ans = []
    
    const dfs = (candidates, s, target, curr, ans) => {
        if (target === 0) {
            ans.push([...curr])
            return
        }
        
        for (let i = s; i < candidates.length; ++i) {
            if (candidates[i] > target) break
            curr.push(candidates[i])
            dfs(candidates, i, target - candidates[i], curr, ans)
            curr.pop()
        }
    }
    
    dfs(candidates, 0, target, [], ans)
    return ans
};