40.组合总和 II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtrace(vector<int>& candidates, int target,int start,bool note) {
if (target == 0) {
result.push_back(path);
return;
}
if (target < 0) {
return;
}
for (int i = start; i < candidates.size(); i++) {
if(!note && i > 0 && candidates[i-1] == candidates[i]) continue; // 应对重复元素
path.push_back(candidates[i]);
target -= candidates[i];
backtrace(candidates, target, i + 1,true);
note = false;
path.pop_back();
target += candidates[i];
}
}

vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
backtrace(candidates,target,0,false);
return result;
}
};

前面做的组合题,不管强调与否,我们都知道数组中的元素是没有重复的,但这道题恰恰相反。看来只要解决重复元素可能带来的问题就可以了。

首先需要对元素进行排序,这样益于跳过重复的元素,可以说必须做这一步。难道我们只需要判断 前后两个数据是否相同就能忽略重复的元素带来的问题吗?

1
i > 0 && candidates[i-1] == candidates[i]

不是,因为进入 backtrace 中导致本来用来满足需求的元素被忽略,仔细看下面这个例子:

1
candidates = {1,1,1,2,1},target = 2

第一个元素和第二个元素可以组合,但是由于如上的判断条件导致忽略。造成这个的原因是,我们本意忽略的元素是处于同一层的相同元素,但是进入 backtrace 中的元素属于要和上一层元素进行组合的,不应该忽略。

那么我们就用一个布尔值 note 标记,如果 note 为 false 表明在同一层(同一个栈),否则在不同层(不同栈)。同层的元素相同可被忽略,不同层的元素相同不可被忽略。