题目描述
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
算法设计
和39题思路大致相同,也是用深搜。这题还要再加多一个标记数组,用作candidates中每个元素的使用位。当元素被压入结果vector时,使用位记为1。搜索的时候先判断使用位,为1的话跳过该元素。
C++代码
class Solution {
public:
void func(set<vector<int> > &res, vector<int>& candidates, int target, vector<int> tmp, int minus, int index, int tag[]){
if(minus < 0){
return;
}
if(minus == 0){
res.insert(tmp);
return;
}
for(int i=index;i<candidates.size();i++){
if(tag[i] != 0) continue;
tmp.push_back(candidates[i]);
tag[i] = 1;
if(minus - candidates[i] < 0){
tag[i] = 0;
return;
}
func(res, candidates, target, tmp, minus-candidates[i], i, tag);
tmp.pop_back();
tag[i] = 0;
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
int len = candidates.size(), tar = target, tag[len];
memset(tag, 0, sizeof(tag));
vector<vector<int> > res;
set<vector<int> > ress;
if(len <= 0){
return res;
}
vector<int> tmp;
sort(candidates.begin(), candidates.end());
func(ress, candidates, target, tmp, tar, 0, tag);
set<vector<int> >::iterator it = ress.begin();
for(it;it!=ress.end();it++){
res.push_back(*it);
}
return res;
}
};