给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 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]
]
提示:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
因为题目是求“所有可能的组合”,所以很自然想到了递归。感觉一提到组合我的第一反应就是,“对于每个元素,都有选与不选两种选择”,对每个元素分别作出选择后我们就得到了其中一个组合。
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function (candidates, target) {
const dfs = (candidates, ans, remain, cur) => {
if (remain < 0) return;
if (remain === 0) {
res.push(ans);
return;
}
while (cur < candidates.length) {
if (candidates[cur] <= remain) {
ans.push(candidates[cur]);
dfs(candidates, [...ans], remain - candidates[cur], cur);
ans.pop();
}
cur++;
}
};
const res = [];
dfs(candidates, [], target, 0);
return res;
};
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function (candidates, target) {
candidates.sort((a, b) => a - b);
const res = [];
dfs(candidates, 0, target);
return res;
// ******************************************
function dfs(arr, cur, target, tempArr = [], total = 0) {
if (total > target) return;
if (total === target) {
res.push([...tempArr]);
return;
}
// 因为数字可以重复选择,所以 i 从 cur 开始
for (let i = cur; i < arr.length; i++) {
// 剪枝
if (total + arr[cur] > target) break;
// 选当前数字
tempArr.push(arr[i]);
// 递归决定选不选后面的数字
dfs(arr, i, target, tempArr, total + arr[i]);
// 不选当前数字
tempArr.pop();
}
}
};