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.