组合中无重复元素,所有元素可以随便取多少次。那么startIndex就可以从本次遍历处开始。
class Solution {
public:
// 老套路,两个数组前一个存储中间结果,后一个存储总结果集
vector<int> vec;
vector<vector<int>> res;
// 回溯
void backtracking(vector<int>& candidates, int target, int startIndex){
if (target == 0){
res.push_back(vec);
return;
}
// 如果小于0则表示不满足,不需要加入结果集
else if (target < 0){
return;
}
// 对于n叉树的遍历
for (int i = startIndex;i<candidates.size();i++){
target -= candidates[i];
vec.push_back(candidates[i]);
// 还是需要传递startIndex,但是下一级递归可以使用这一级的数,因为可重复
backtracking(candidates, target, i);
target += candidates[i];
vec.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates, target, 0);
return res;
}
};
这一次变为组合中有重复元素,但是每一个元素只能使用一次。那么就需要先对组合元素排序,如果相邻元素相同只需要遍历一次,否则可能造成结果集重合。
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& candidates, int target, int startIndex){
if (target == 0){
res.push_back(path);
return;
}
if (target < 0){
return;
}
for (int i = startIndex; i<candidates.size();i++){
// 这里同层的相同元素直接跳过,否则会出现重复
if (i > startIndex && candidates[i] == candidates[i-1])
continue;
target -= candidates[i];
path.push_back(candidates[i]);
backtracking(candidates, target, i+1);
target += candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
// 这个方法需要先排序
sort(candidates.begin(), candidates.end());
backtracking(candidates, target,0);
return res;
}
};
没想到分割回文串也是组合问题的延续。难点在于分割点的选取,子串获取,回文串判断要单独写出。总之是一道经典难题吧。还需要再练习。
class Solution {
private:
// 不会写,抄的
vector<string> path;
vector<vector<string>> res;
void backtracking(const string& s, int startIndex){
// 结束条件 startIndex表示切割的起始位置
if (startIndex >= s.size()){
res.push_back(path);
return;
}
// 横向切割
for (int i = startIndex; i < s.size(); i++){
if (isPalindrome(s, startIndex, i)){
// substr函数的参数为begin,len,表示[begin, begin+len)的子串
string str = s.substr(startIndex, i - startIndex + 1);
path.push_back(str);
}
else{
continue;
}
// 切割点向后移动
backtracking(s, i+1);
// 回溯
path.pop_back();
}
}
// 双指针法判断是否是回文串
bool isPalindrome(const string& s, int start, int end){
for (int i = start,j=end; i < j;i++,j--){
if (s[i] != s[j])
return false;
}
return true;
}
public:
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
};