Leetcode 40. 组合总和 II
题目
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
思路
-
递归函数和参数
candidates,目标值target,path中数字之和sum,控制for循环起始位置startIndex,标记数组bool型used -
递归终止条件
sum > targetSum 或者 sum = targetSum -
单层搜索逻辑
通过for循环来搜索每一层,但是需要去重,当candidates[i] = candidates[i - 1] 并且used[i - 1] = false说明前一个树枝已经使用过了candidates[i - 1],也就是同一个数层使用过该元素candidates[i - 1],跳过该元素。其余的操作同39.组合总和这一题
代码
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backTracking(vector<int>& candidates,int target,int startIndex,vector<bool>& used,int sum)
{
if(sum > target)
{
return;
}
if(sum == target)
{
result.push_back(path);
return;
}
for(int i = startIndex; i < candidates.size(); i++)
{
// 同一树层 横向去重 不可以取相同的元素
if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false)
{
// 说明该元素已经使用过
continue;
}
sum += candidates[i];
path.push_back(candidates[i]);
used[i] = true;// 标记已经使用过
backTracking(candidates,target,i + 1,used,sum);// 每一个元素 组合中只能使用一次 所以是i + 1
// 回溯操作
used[i] = false;
path.pop_back();
sum -= candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
result.clear();
path.clear();
vector<bool> used(candidates.size(),false);
// 首先将数组进行排序 相同的元素排在一起
sort(candidates.begin(),candidates.end());
backTracking(candidates,target,0,used,0);
return result;
}
};