【问题】给定一个无重复元素的数组 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]
]【思路】
-
首先我们要来考虑的是,dfs的参数,首先两个不变的参数candidates和target, 接着是两个可变的参数,一个用来计算我们搜索的组合的和sum,另外一个标记开始搜索的位置start。
递归的退出条件:当sum >= target时,或者开始位置超出了candidate的边界
由于题目中说,元素可以任意使用,但是组合不可以重复,因此我们需要注意:-
在dfs函数中for循环的开始值为start, 表示从某一位置开始,并不会使用此位置之前的值,避免出现[2,2,3], [2,3,2]这种重复的组合!也就是说组合必须为非减序列!
-
又因为元素可以重复使用,因此dfs在for循环调用时,i并没有加一!因此下一个子方法还是可以使用当前元素!
-
注意d数组的状态,dfs结束后要将其状态恢复,然后才可以重复使用!
-
-
class Solution { vector<int> d; vector<vector<int> > res; private: void dfs(vector<int>& candidates, int sum, int target, int start){ if(sum >= target || start == candidates.size()){ if(sum == target) res.push_back(d); return; } for(int i = start;i < candidates.size();i++){ // 遍历从start开始,避免重复使用之前的值,造成重复 d.push_back(candidates[i]); // 但每次进入函数都要从当前位置进入,可以使用重复值 dfs(candidates, sum+candidates[i], target, i); d.pop_back(); } } public: vector<vector<int> > combinationSum(vector<int> &candidates, int target) { sort(candidates.begin(), candidates.end()); dfs(candidates, 0, target, 0); return res; } };