LeetCode CombinationSum II

class Solution {
public:
    vector<vector<int> > combinationSum2(vector<int> &num, int target) {
        sort(num.begin(), num.end());
        
        vector<vector<int> > tmp;
        vector<int> sel;
        dfs(num, 0, target, sel, tmp);
        return tmp;
    }
    
    void dfs(vector<int> &num, int pos, int target, vector<int>& sel, vector<vector<int> >& res) {
        if (target == 0) {
            res.push_back(sel);
            return;
        }
        if (pos >= num.size()) return;
        int cur = num[pos];
        int dup = 0;        
        int i = pos;
        while (++i < num.size() && num[i] == cur) dup++;
        
        int add = 0;

        for (i = 0; (i <= dup + 1) && add <= target; i++, add+=cur) {
            if (i != 0) {
                sel.push_back(cur);
            }
            dfs(num, pos + dup + 1, target - add, sel, res);
        }
        for (i = add/cur - 1; i>0; i--) sel.pop_back();
    }
    
};

类似01背包,不过这是求和,虽然说每个元素最多用一次,但是从例子中发现,所给的候选数时会有重复的。因为输出要求不能有重复,这时我们可以把多个重复的候选数看成是同一个数取[0, k]次(k为该数出现的次数)这和最初的CombinationSum中类似(只不过这里指定了每个元素出现的次数,而不是原先的可以取无限次),这相当于把重复的候选数压到了一个位置上,当我们在该位置做出取(一次性取n,n<=k)和不取两种选择后,后面再也不会对该数考虑相同的问题,这使得我们可以避免输出雷同解。

原文地址:https://www.cnblogs.com/lailailai/p/3606148.html