题目描述
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
样例
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
算法
(递归枚举)
- 做法与 Combination Sum 很类似,只不过本题是每个数字仅用一次。
- 此题仍然需要排序,目的是为了防止重复。
- 防止重复的方法是,搜索时如果不想要当前层的数字,则需要找到下一个与之不同的数字才可以进行下一层的搜索。
C++ 代码
class Solution {
public:
void solve(int i, vector<int>& candidates, int sum,
vector<int>& ch, int target, vector<vector<int>>& ans) {
// 注意这里的 ch 是引用。
if (sum == target) {
ans.push_back(ch);
return;
}
if (i == candidates.size() || sum > target)
return;
for (int j = i + 1; j < candidates.size(); j++)
if (candidates[j] != candidates[i]) {
// 不用该层的数字时,需要找到下一个不同的数字。
solve(j, candidates, sum, ch, target, ans);
break;
}
// 选择该层的数字。
ch.push_back(candidates[i]);
solve(i + 1, candidates, sum + candidates[i], ch, target, ans);
ch.pop_back();
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<vector<int>> ans;
sort(candidates.begin(), candidates.end());
vector<int> ch; // ch 记录选择的数字。
solve(0, candidates, 0, ch, target, ans);
return ans;
}
};
选或不选好写法
wls 为啥需要找到下一个与之不同的数字才可以进行下一层的搜索?
:)
在决定不选当前数字的时候,如果下一个数字还是相同的就会导致重复。
如果不选x的话就跳过所有的x,这个地方怎么理解呢?想不明白。。
因为重复选
x
会导致重复呀这个题目能不能像39那样把一个递归用for循环来代替?
没太懂你的思路额
老哥,这里为啥是引用啊,跟39有啥区别吗
如果不是引用,则
ch
在每一次递归时都会调用拷贝构造函数复制一份传参,效率低,参考如下代码:f
中的a
就是拷贝了一份后的a
。我更新了 39 的一版 C++ 代码,为了和 40 题的代码相似。
可以做一下 LC 797 巩固这个写法。
请问这个复杂度怎么分析?
复杂度应该是指数级的