题目描述:
难点:集合(数组candidates)有重复元素,但还不能有重复的组合
方法1:回溯
class Solution {
public:
vector<vector<int>> result;
vector<int> data;
void backtrack(vector<int>& candidates, int target,int sum,int StartIndex){
if(sum==target){
result.push_back(data);
return;
}
if(sum > target) return;
for(int i=StartIndex;i<candidates.size();i++){
data.push_back(candidates[i]);
sum += candidates[i];
backtrack(candidates,target,sum,++StartIndex);
sum -= candidates[i];
data.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
backtrack(candidates,target,0,0);
return(result);
}
};
出错,该题数组中可能出现重复数字,导致后续输出中会出现重复的组合。(组合总和Ⅰ)中为无重复数组
修改:去重,使用unordered_set
class Solution {
public:
vector<vector<int>> result;
vector<int> data;
void backtrack(unordered_set<int> set, int target,int sum,int j){
if(sum==target){
result.push_back(data);
return;
}
if(sum > target) return;
auto index = set.begin();
for(int i=0;i<j;i++) index++;
for(auto it=index;it != set.end();it++){
data.push_back(*it);
sum += *it;
backtrack(set,target,sum,++j);
sum -= *it;
data.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
unordered_set<int>set;
for(int i=0;i<candidates.size();i++){
set.emplace(candidates[i]);
}
backtrack(set,target,0,0);
return(result);
}
};
出错,把[1,7],[7,1]的重复去了,但是也把[1,1,6]这样的也去了(元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同)
修改:不使用set,先对数组排序,然后相等元素在每一轮中只被选择一次
class Solution {
public:
vector<vector<int>> result;
vector<int> data;
void backtrack(vector<int>& candidates, int target,int sum,int StartIndex){
if(sum==target){
result.push_back(data);
return;
}
if(sum > target) return;
for(int i=StartIndex;i<candidates.size();i++){
if(i>StartIndex && candidates[i] == candidates[i-1]) continue;
data.push_back(candidates[i]);
sum += candidates[i];
backtrack(candidates,target,sum,i+1); //纵向
sum -= candidates[i];
data.pop_back();//回退后下一轮为横向,横向不可以重复,纵向可以
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
backtrack(candidates,target,0,0);
return result;
}
};
注:
加上 if(i>StartIndex && candidates[i] == candidates[i-1]) continue;保证横向取时不会取到重复的
和39.组合总和的区别 backtrack(candidates,target,sum,i+1),这里是i+1,每个数字在每个组合中只能使用一次,在组合总和中为i