代码随想录算法训练营day23 | 39. 组合总和、40.组合总和II、131.分割回文串
- 组合总和
点击查看代码
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates, int &target, int sum, int startIndex) {
//由于for循环条件已经提前做了递归终止判断,故这里不用再加
//if(sum > target) return;
if(sum == target) {
result.push_back(path);
}
//&& sum + candidates[i] <= sum,剪枝,由于candidates数组经过排序
//故若上一层传下来的sum + 本层的某一元素已经大于target,则+本元素的后
//续元素也必然大于target,故提前结束本层循环遍历,也不再往下递归
for(int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; ++i) {
path.push_back(candidates[i]);
//下一层的startIndex仍为i,因为同一个数字可重复选取
backtracking(candidates, target, sum + candidates[i], i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
//先排序,方便后续剪枝
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return result;
}
};
注意本题的剪枝操作,同时注意当题目可以重复选取某一元素时,传入下一层函数的startIndex值的选取
40.组合总和II
去重解法一:使用used数组
点击查看代码
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
vector<bool> used;
void backtracking(vector<int>& candidates, int &target, int sum, int startIndex) {
if(sum == target) {
result.push_back(path);
return;
}
for(int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; ++i) {
//去重逻辑:树枝不去重,树层去重
if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) continue;
path.push_back(candidates[i]);
used[i] = 1;
//此处i+1是因为candidates中的每个数字在每个组合中只能使用一次
backtracking(candidates, target, sum + candidates[i], i + 1);
used[i] = 0;
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
used.resize(candidates.size(), false);
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return result;
}
};
去重解法二:直接使用startIndex进行去重
点击查看代码
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates, int &target, int sum, int startIndex) {
if(sum == target) {
result.push_back(path);
return;
}
for(int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; ++i) {
//去重逻辑:树枝不去重,树层去重
//i = startIndex为本树层的第一个元素,不可能重复,若此时
//candidates[i] == candidates[i - 1],说明是树枝上的重复,无需去重
//当i > startIndex且candidates[i] == candidates[i - 1],此时才是树层上重复,需要去重
if(i > startIndex && candidates[i] == candidates[i - 1]) continue;
path.push_back(candidates[i]);
//此处i+1是因为candidates中的每个数字在每个组合中只能使用一次
backtracking(candidates, target, sum + candidates[i], i + 1);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return result;
}
};
131.分割回文串
点击查看代码
class Solution {
public:
vector<vector<string>> result;
vector<string> path;
bool isHuiWen(string &s, int left, int right) {
while(left < right) {
if(s[left] != s[right]) return false;
left++;
right--;
}
return true;
}
void backtracking(string &s, int startIndex){
if(startIndex == s.size()) { //能到达这个if判断的说明已切的均为回文串,否则不会递归到这
result.push_back(path);
return;
}
for(int i = startIndex; i < s.size(); ++i) {
if(isHuiWen(s, startIndex, i)) {
path.push_back(s.substr(startIndex, i - startIndex + 1));
}
else continue; //不是回文串则继续往后切,不进行递归,是回文串才往下递归
backtracking(s, i + 1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return result;
}
};

每一层for循环中,[startIndex, i]区间即为所切割的区间,需要判断这个区间的子串是否为回文串,是的话则放入path中,不是的话再往后切割
2025/03/05

浙公网安备 33010602011771号