第一题:
原题链接:39. 组合总和 - 力扣(LeetCode)
思路:
终止条件:
用一个sum值来记录当前组合中元素的总和。当sum的值大于target的时候证明该组合不合适,直接return。当sum的值等于target的时候将组合添加到组合集合中。
for循环中注意本题中的元素是可以重复选取的,因此下层递归中的startIndex还是i。
剩下的就是回溯的模板。
代码如下:
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
if(candidates.size() == 0) return {};
backtracking(candidates, target, 0, 0);
return res;
}
private:
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++){
path.push_back(candidates[i]);
sum += candidates[i];
backtracking(candidates, target, sum, i);
sum -= candidates[i];
path.pop_back();
}
}
};
第二题:
原题链接:40. 组合总和 II - 力扣(LeetCode)
思路:
本题要注意的是去重的逻辑。
首先我们对数组进行排序,让相同的元素紧挨着。方便我们进行去重的逻辑。
Carl提到了树层和树枝去重的概念,这个概念很便于理解。本题要注意的就是树层去重的逻辑。树枝上不需要去重,因为树枝上的元素对应的是不同的元素。而树层上的元素必须要去重,因为在树枝上前一个相同的元素的遍历会包含当前元素的所有遍历结果,因此如果在同一层中当前的元素和前一个元素相同并且前一个元素没有被使用过的情况下,该元素直接跳过。
同时我们需要一个bool类型的数组来记得什么元素已经使用过了。当我们使用过的话将该数组对应的位置置为true;
代码如下:
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<bool> used(candidates.size(), false);
backtracking(candidates, target, 0, 0, used);
return res;
}
private:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex, vector<bool>& used){
if(sum > target)return;
if(sum == target){
res.push_back(path);
return;
}
for(int i = startIndex; i < candidates.size(); i++){
if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false){
continue;
}
path.push_back(candidates[i]);
used[i] = true;
sum += candidates[i];
backtracking(candidates, target, sum, i + 1, used);
used[i] = false;
sum -= candidates[i];
path.pop_back();
}
}
};
第三题:
原题链接:131. 分割回文串 - 力扣(LeetCode)
思路:
需要一根指针来指向当前分割的位置。
for循环是用来看在以startIndex为分割线,以i为结束的子串是否为回文串。
在递归的逻辑中是将startIndex的位置向后移动一位。
代码如下:
class Solution {
public:
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
private:
vector<vector<string>> res;
vector<string> path;
void backtracking(string s, int startIndex){
if(startIndex == s.size()){
res.push_back(path);
return;
}
for(int i = startIndex; i < s.size(); i++){
if(!isHuiwen(s, startIndex, i)) continue;
string st = s.substr(startIndex, i - startIndex + 1);
path.push_back(st);
backtracking(s, i + 1);
path.pop_back();
}
}
bool isHuiwen(const string& s, int start, int end){
while(start < end){
if(s[start] == s[end]){
start++;
end--;
}else{
return false;
}
}
return true;
}
};