Given a collection of candidate numbers (candidates
) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
Each number in candidates
may only be used once in the combination.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
Example 2:
Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
[1,2,2],
[5]
]
题目: 给定一个候选元素的数组candidates
,找出满足和为target
的所有子集。candidates
可能包含重复的元素,只能使用candidates
中存在的元素。
思路: 和4sum类似,只是这里的递归深度不定,递归返回的条件是remain
已经等于0,参考A general approach to backtracking questions。同时由于题目的特殊性,candidates
中的元素和target
均为正数,所以当remain
小于0时也可以直接返回,减少递归的次数。为了防止结果中出现重复的集合,先对candidates
排序,同时在每层递归中跳过已经判断过的相同元素。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int> > res;
vector<int> vec;
helper(candidates, res, vec, 0, target);
return res;
}
private:
void helper(vector<int>& candidates, vector<vector<int>>& res, vector<int>& vec, int start, int remain){
/** All numbers (including target) will be positive integers. **/
if(remain < 0)
return;
if(remain == 0){
res.push_back(vec);
return;
}
for(int i = start; i< candidates.size(); ++i){
/** skip duplicates */
if(i > start && candidates[i] == candidate[i-1])
continue;
vec.push_back(candidates[i]);
helper(candidates, res, vec, i+1, remain-candidates[i]);
vec.pop_back();
}
}
};
int main(int argc, char const *argv[])
{
Solution sln;
vector<int> testcase{10,1,2,7,6,1,5};
vector<vector<int>> res = sln.combinationSum2(testcase, 8);
for(auto vec: res){
for(auto i : vec)
cout << i << ",";
cout << endl;
}
return 0;
}