34,Leetcode 组合总和I,II -C++ 回溯法
I 题目描述
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。说明:所有数字(包括 target)都是正整数。解集不能包含重复的组合。 示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
I 题解
回溯法。回溯法本质上是一种搜索算法;要实现回溯,需要两点:搜索和解空间。 解题方法通常为递归。
回溯算法将解空间看作一定的结构,通常为树形结构,一个解对应于树中的一片树叶。算法从树根(即初始状态出发),尝试所有可能到达的结点。当不能前行时就后退一步或若干步,再从另一个结点开始继续搜索,直到尝试完所有的结点。也可以用走迷宫的方式去理解回溯,设想把你放在一个迷宫里,想要走出迷宫,最直接的办法是什么呢?没错,试。先选一条路走起,走不通就往回退尝试别的路,走不通继续往回退,直到走遍所有的路,并且在走的过程中你可以记录所有能走出迷宫的路线。
最终,
168/168 cases passed (8 ms)。
Your runtime beats 99.75 % of cpp submissions。
Your memory usage beats 98.76 % of cpp submissions (9.1 MB)。
I C++代码
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<vector<int>> res;
vector <int > tmp;
backtracking(0,target,candidates,tmp,res);
return res;
}
void backtracking(int i,int target,vector<int>& candidates,vector<int>&tmp,vector<vector<int>>&res){
if (target < 0)
return;
if(target == 0){
res.push_back(tmp);
return;
}
for(int j=i; j<candidates.size();j++){
if(target < candidates[j])
break;
tmp.push_back(candidates[j]);
backtracking(j,target-candidates[j],candidates,tmp,res);
tmp.pop_back();
}
}
};
II 题目描述
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
示例 1:
输入:
candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入:
candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
II 题解
回溯法。
- 因为每个元素只能用一次,所以递归时需要从下一个元素开始。
- 因为candidates元素有重复,所以得到的解空间也会有重复,需要去重。
同一个父节点下不能有重复的叶节点。,所以遇到相同的便跳过。
if(j>i && candidates[j]==candidates[j-1])
AC,
172/172 cases passed (8 ms)Your runtime beats 94.72 % of cpp submissionsYour memory usage beats 93.16 % of cpp submissions (8.9 MB)。
II C++代码
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<vector<int>> res;
vector<int> tmp;
backtracking(0,target,candidates,tmp,res);
return res;
}
void backtracking(int i,int target,vector<int>& candidates,vector<int> &tmp,vector<vector<int>> &res){
if(target < 0)
return;
if(target == 0){
res.push_back(tmp);
return;
}
for(int j=i; j < candidates.size(); j++){
if(target < candidates[j])
break;
if(j>i && candidates[j]==candidates[j-1])
continue;
//if(j<candidates.size()-1 && candidates[j+1]==candidates[j])
// continue;
tmp.push_back(candidates[j]);
backtracking(j+1,target-candidates[j],candidates,tmp,res);
tmp.pop_back();
}
}
};