题目描述
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
示例1:
输入: nums= [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例2:
输入: nums= [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
解题思路:
使用递归+回溯思想
此题目与LeetCode90—子集Ⅱ解法类似
只是需要考虑所得的子集内的数字之和等于target
若是直接求出子集,然后再遍历每一个子集求出和,然后再与target比较,此时会出现超时。
所以使用回溯中的剪枝来实现,即剪掉不必要的数字,如果当前集合内的数字之和已经大于target,则不用再往下计算,直接返回即可
//i表示nums的下标
//nums表示给定的数组
//item表示组成的子集
//result表示结果集
//res_set用来去重
//sum表示当前集合中元素的和
//target表示给定的目标值
void generate(int i, vector<int>& nums, vector<int>& item, vector< vector<int> >& result, set< vector<int> > &res_set, int sum, int target) {
if (i >= nums.size() || sum > target) {
return;
}
sum += nums[i];
item.push_back(nums[i]);
if ((sum == target) && res_set.find(item) == res_set.end()) {
result.push_back(item);
res_set.insert(item);
}
generate(i + 1, nums, item, result, res_set, sum, target);
sum -= nums[i];
item.pop_back();
generate(i + 1, nums, item, result, res_set, sum, target);
}
//组合总和Ⅱ
vector<vector<int>> combinationSum2(vector<int>& nums, int target) {
vector< vector<int> > result;
vector<int> item;
int sum = 0;
set< vector<int> > res_set;
sort(nums.begin(), nums.end());
generate(0, nums, item, result, res_set, sum, target);
return result;
}