- 组合总和
点击查看代码
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