0
点赞
收藏
分享

微信扫一扫

leetcode 40. 组合总和 II 思考分析

题目

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
leetcode 40. 组合总和 II 思考分析_算法
leetcode 40. 组合总和 II 思考分析_剪枝_02

思考以及代码

如果我们直接套用39题​的思路,那么就会出现重复的组合。
leetcode 40. 组合总和 II 思考分析_剪枝_03
重复组合的产生,是因为集合中有重复的元素。
去重,就是使用过的元素不能重复选取。
我们result的重复组合的产生肯定是和重复元素有关的,我们从解空间树的深度(递归调用)和宽度(for循环)来看:
1、元素的重复的影响可能出现在在解空间树的宽度和深度上。
2、宽度上的重复决定了我们result解的组合的重复,深度上的重复决定了result解的每个子结果res的元素重复。
3、结合题意:如果是在宽度上重复我们需要去除,如果是在深度上重复我们不需要去除。

在宽度上进行去重所以我们在for循环的过程中加入限制。

//如果遇到同一个集合的重复元素,跳过这个元素即可
if(i > startindex && candidates[i] == candidates[i-1]) continue;

注意这里我们已经对原数组进行排序了,所以重复的元素一定靠在一起

class Solution {
public:
vector<vector<int>> result;
vector<int> res;
int sum;
void clear_solution_param()
{
result.clear();
res.clear();
sum=0;
}
void backtracking(vector<int>& candidates,int startindex,int n)
{
if(sum > n) return;
if(sum == n)
{
result.push_back(res);
return;
}
for(int i=startindex;i<candidates.size();i++)
{
//由于输入的数组是有序的,所以直接进行剪枝。如果sum加上这个集合元素大于目标,此层就不需要往后看了,因为后面的元素加上sum肯定大于目标
if(sum+candidates[i]>n) break;
//如果遇到同一个集合的重复元素,跳过这个元素即可
if(i > startindex && candidates[i] == candidates[i-1]) continue;
//处理结点;
res.push_back(candidates[i]);
sum+=candidates[i];
//递归,探索下一层
backtracking(candidates,i+1,n); //递归
sum-=candidates[i];
//回溯,撤销处理结果
res.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
clear_solution_param();
//排序加速剪枝
sort(candidates.begin(),candidates.end());
backtracking(candidates,0,target);
return result;
}
};


举报

相关推荐

0 条评论