【问题】给定一个无重复元素的数组 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;
        }
    };