leetcode 组合总和II 中等

 

 

dfs 可以很好的解决这个问题。

主要是如何去重:

① 哈希去重,不过会带来一定的复杂度

② 先对数组排序,看代码:

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<int> path;
        solve(candidates, 0, target, path);
        return ret;
    }

private:
    vector<vector<int>> ret;

    void solve(const vector<int>& candidates, int i, int target, vector<int> &path) {
        if(target == 0) {
            ret.emplace_back(path);
            return ;
        }
        for(int j = i; j < candidates.size(); ++ j) {
            if(j > i && candidates[j] == candidates[j - 1]) continue;
            if(target < candidates[j]) break;
            path.emplace_back(candidates[j]);
            solve(candidates, j + 1, target - candidates[j], path);
            path.pop_back();
        }
    }
};

 

去重原理 (https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-3/):

这个方法最重要的作用是,可以让同一层级,不出现相同的元素。即
                  1
                 / \
                2   2  这种情况不会发生 但是却允许了不同层级之间的重复即:
               /     \
              5       5
                例2
                  1
                 /
                2      这种情况确是允许的
               /
              2  
                
为何会有这种神奇的效果呢?
首先 cur-1 == cur 是用于判定当前元素是否和之前元素相同的语句。这个语句就能砍掉例1。
可是问题来了,如果把所有当前与之前一个元素相同的都砍掉,那么例二的情况也会消失。 
因为当第二个2出现的时候,他就和前一个2相同了。
                
那么如何保留例2呢?
那么就用cur > begin 来避免这种情况,你发现例1中的两个2是处在同一个层级上的,
例2的两个2是处在不同层级上的。
在一个for循环中,所有被遍历到的数都是属于一个层级的。我们要让一个层级中,
必须出现且只出现一个2,那么就放过第一个出现重复的2,但不放过后面出现的2。
第一个出现的2的特点就是 cur == begin. 第二个出现的2 特点是cur > begin.
posted @ 2021-09-20 20:03  rookie_Acmer  阅读(32)  评论(0编辑  收藏  举报