- 题目:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题思路:
看到这种需要不断组合来进行解决的题目,最直接的思路就是使用DFS,通俗来讲就是使用回溯算法,这和之前的题目是类似的。
重点就是回溯算法该怎么写。
这里我给出了两种解法。
3. 解题代码:
第一种解法:这种是直接对target进行减法的运算,直到target = 0结束。
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
int length = candidates.size();
//先对vector进行排序
sort(candidates.begin(),candidates.end());
vector<vector<int>> res;
vector<int> current;
if(length == 0){
return {};
}
if(candidates[0] > target){
return {};
}
DFS(res,candidates,target,current,0);
return res;
}
void DFS(vector<vector<int>> &res,vector<int> candidates,int target,vector<int> ¤t,int deep){
//终止条件
if(target == 0){
res.push_back(current);
return;
}
for(int i = deep; i < candidates.size() && target > 0;i++){
//对同一树层使用过的数组进行去重
if(i > deep && candidates[i] == candidates[i-1]){
continue;
}
target = target - candidates[i];
current.push_back(candidates[i]);
DFS(res,candidates,target,current,i+1);
target += candidates[i];
current.pop_back();
}
}
};
第二种解法:这种解法是每次对sum进行加法运算,直到sum = target 结束。
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
int length = candidates.size();
//先对vector进行排序
sort(candidates.begin(),candidates.end());
vector<vector<int>> res;
vector<int> current;
if(length == 0){
return {};
}
if(candidates[0] > target){
return {};
}
DFS(res,candidates,target,current,0,0);
return res;
}
void DFS(vector<vector<int>> &res,vector<int> candidates,int target,vector<int> ¤t,int deep,int sum){
//终止条件(对结果进行收集)
if(target == sum){
res.push_back(current);
return;
}
// 每次搜索的宽度
for(int i = deep; i < candidates.size() && sum + candidates[i] <= target ;i++){
//处理结点
//对同一树层使用过的数组进行去重
if(i > deep && candidates[i] == candidates[i-1]){
continue;
}
sum = sum + candidates[i];
current.push_back(candidates[i]);
//递归
DFS(res,candidates,target,current,i+1,sum);
//回溯
sum -= candidates[i];
current.pop_back();
}
}
};
- tips:
熟记回溯算法的大致框架,在回溯时一定要对保存当前数组进行弹出,还要对已经组成的和进行减法运算。