一、题目
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
二、解法
看到组合,就想到回溯法。
关键在于回溯法函数,
void dfs(vector<int>& cur,int target,int idx)
伪代码原型:cur是当前的组合,target是当前的目标,idx是当前选取元素的下标。
- 结束条件:target<=0或者idx超出数组边界
- 回溯:可以不选取idx的元素,继续下一次dfs,则idx+1
- 也可以选取idx的元素,则target要减少,idx不变。
关键点:先对candidates数组进行升序排列,当target<candidates[idx]时,认为后面的元素都比target大,直接返回(相当于剪枝)
class Solution {
public:
void dfs(vector<vector<int>>& ans,vector<int>& candidates,int target,vector<int>& cur,int idx){
if(idx==candidates.size()||target<0) return;
if(target==0){
ans.emplace_back(cur);
return;
}
if(target>=candidates[idx]){ //candidates升序排列,若target比当前数小,则直接跳过
//跳过当前数
dfs(ans,candidates,target,cur,idx+1);
//算上当前数
cur.push_back(candidates[idx]);
dfs(ans,candidates,target-candidates[idx],cur,idx);
cur.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<vector<int>> ans;
vector<int> cur;
dfs(ans,candidates,target,cur,0);
return ans;
}
};