39. 组合总和
https://leetcode.cn/problems/combination-sum/
本题还需要startIndex来控制for循环的起始位置,对于组合问题,什么时候需要startIndex呢?
如果是一个集合来求组合的话,就需要startIndex,例如:77.组合 (opens new window),216.组合总和III (opens new window)。
如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:17.电话号码的字母组合
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if(sum > target) return ;
if(sum == target){
res.push_back(path);
return ;
}
for(int i = startIndex; i < candidates.size(); i++){
sum += candidates[i];
path.push_back(candidates[i]);
backtracking(candidates, target, sum, i);
path.pop_back();
sum -= candidates[i];
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates, target, 0, 0);
return res;
}
};
40.组合总和II
https://leetcode.cn/problems/combination-sum-ii/
这道题目和39.组合总和 (opens new window)如下区别:
- 本题candidates 中的每个数字在每个组合中只能使用一次。
- 本题数组candidates的元素是有重复的,而39.组合总和 (opens new window)是无重复元素的数组candidates
最后本题和39.组合总和 (opens new window)要求一样,解集不能包含重复的组合。
本题的难点在于区别2中:集合(数组candidates)有重复元素,但还不能有重复的组合。
回看一下题目,元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if(sum > target) return ;
if(sum == target){
res.push_back(path);
return ;
}
for(int i = startIndex; i < candidates.size(); i++){
if(i > startIndex && candidates[i] == candidates[i - 1]) continue;
path.push_back(candidates[i]);
sum += candidates[i];
backtracking(candidates, target, sum, i + 1);
sum -= candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return res;
}
};
131.分割回文串
https://leetcode.cn/problems/palindrome-partitioning/
切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的
class Solution {
public:
vector<vector<string>> res;
vector<string> path;
bool isPalindrome(string s, int l, int r){
for(int i = l, j = r; i < j; i++, j--){
if(s[i] != s[j]) return false;
}
return true;
}
void backtracking(string s, int startIndex){
if(startIndex == s.size()){
res.push_back(path);
return ;
}
for(int i = startIndex; i < s.size(); i++){
if(isPalindrome(s, startIndex, i)){
string str = s.substr(startIndex, i - startIndex + 1);
path.push_back(str);
backtracking(s, i + 1);
path.pop_back();
}
else continue;
}
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
};