力扣 leetcode 40. 组合总和 II
问题描述
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
提示:
- 1 <= candidates.length <= 100
- 1 <= candidates[i] <= 50
- 1 <= target <= 30
示例
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
解题思路
基本思路参照力扣 leetcode 39. 组合总和,这里添加的限制是数组中每个元素只能使用一次。因此,我们要避免两种重复:一是重复使用同一个数组元素;二是上一轮遍历时使用的元素与这一轮遍历时使用的元素的值相同。
在之前代码的基础上,我们稍作修改,用一个变量 pre 来记录上一轮遍历时所用的数组元素的值,避免重复。
class Solution {
public:
void pushItem(vector<int>& candidates, vector<vector<int>>& res, int target, vector<int>& r, int n, int idx){
if(!target){ // 保存结果
vector<int> tmp(n);
for(int i = 0; i < n; i++){
tmp[i] = r[i];
}
res.push_back(tmp);
return;
}
int pre = -1;
for(int i = idx; i < candidates.size(); i++){
if(pre == candidates[i]){ // 如果此次遍历时,元素与上一轮相同,那么就是重复的,应该跳过
continue;
}
if(candidates[i] <= target){
if(n < r.size()){
r[n] = candidates[i];
}
else{
r.emplace_back(candidates[i]);
}
pushItem(candidates, res, target - candidates[i], r, n + 1, i + 1);
pre = candidates[i];
}
else{
break;
}
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<int> r;
vector<vector<int>> res;
pushItem(candidates, res, target, r, 0, 0);
return res;
}
};
本文来自博客园,作者:greatestchen},转载请注明原文链接:https://www.cnblogs.com/greatestchen/p/16967803.html