39. 组合总和
本题和前面写过的区别是可以重复取数。但仍然是无序,所以宽度上取过的数还是不可以再取。
对于组合问题,什么时候需要startIndex呢?
如果是一个集合来求组合的话,就需要startIndex;如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex。
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backtracking(vector<int>& candidates, int target, int startindex){
if(target<0){
return;
}
if(target==0){
result.push_back(path);
return;
}
for(int i=startindex;i<candidates.size();i++){
path.push_back(candidates[i]);
target-=candidates[i];
backtracking(candidates, target,i);
target+=candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates,target,0);
return result;
}
};
40.组合总和II
本题的集合中有重复元素,但是解集中不能包括重复的答案。
也就是for循环的时候不可以选之前选过的数。
也就是在树层 这个层面进行去重,树层去重的话,需要对数组排序
关于引入的used数组:
- used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
- used[i - 1] == false,说明同一树层candidates[i - 1]使用过
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backtracking(vector<int>& candidates, int target, int startindex, vector<bool>& used){
if(target==0){
result.push_back(path);
return;
}
for(int i=startindex;i<candidates.size() && target-candidates[i]>=0;i++){
if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {
continue;
}
target-=candidates[i];
path.push_back(candidates[i]);
used[i]=true;
backtracking(candidates,target,i+1,used);
used[i]=false;
path.pop_back();
target+=candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool> used(candidates.size(), false);
sort(candidates.begin(),candidates.end());
backtracking(candidates,target,0,used);
return result;
}
};
131.分割回文串
终止条件的判断。
class Solution {
public:
vector<string> path;
vector<vector<string>> result;
bool isPalindrome(const string& s,int start, int end){
while(start<end){
if(s[start]!=s[end]){
return false;
}
start++;
end--;
}
return true;
}
void backtracking(const string& s, int startindex){
if(startindex>s.size()-1){
result.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);
}
else{
continue;
}
backtracking(s,i+1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return result;
}
};
总结
这部分的回溯和昨天类似,多了去重这一操作。关于for循环和回溯函数的嵌套更清晰了