代码随想录day23回溯算法2
文章目录
- 39. 组合总和
- 40. 组合总和 II
- 131. 分割回文串
void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}
39. 组合总和
题目链接
文章讲解
class Solution {
public:vector<vector<int>> ans; // 存储所有符合条件的组合vector<int> path; // 当前组合路径int sum = 0; // 当前路径和// 回溯函数void solve(int target, int n, int start, int sum, vector<int>& candidates) {// 如果当前和超过目标,返回if (sum > target) {return;}// 如果当前和等于目标,将路径加入结果if (sum == target) {ans.push_back(path);return;}// 遍历候选数组,从 start 开始,避免重复for (int i = start; i < n; i++) {path.push_back(candidates[i]); // 选择当前数字sum += candidates[i]; // 更新和solve(target, n, i, sum, candidates); // 递归sum -= candidates[i]; // 回溯,撤销选择path.pop_back(); // 回溯,移除最后一个数字}}// 主函数vector<vector<int>> combinationSum(vector<int>& candidates, int target) {int n = candidates.size();solve(target, n, 0, 0, candidates); // 从 0 开始递归return ans; // 返回所有组合}
};
40. 组合总和 II
题目链接
文章讲解
class Solution {
public:vector<vector<int>> ans; // 存储所有符合条件的组合vector<int> path; // 当前组合路径// 回溯函数,递归生成组合void solve(int target, vector<int>& candidates, int sum, int start) {// 如果当前和超过目标,返回if (sum > target) {return;}// 如果当前和等于目标,将路径加入结果if (sum == target) {ans.push_back(path);return;}// 遍历候选数组for (int i = start; i < candidates.size(); i++) {// 跳过相同的数字,避免重复组合if (i > start && candidates[i] == candidates[i - 1]) {continue;}path.push_back(candidates[i]); // 选择当前数字sum += candidates[i]; // 更新和solve(target, candidates, sum, i + 1); // 递归调用,i + 1 确保每个数字只能使用一次sum -= candidates[i]; // 回溯,撤销选择path.pop_back(); // 回溯,移除最后一个数字}}// 主函数,返回所有符合条件的组合vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end()); // 排序,帮助去重solve(target, candidates, 0, 0); // 从 0 开始递归return ans; // 返回所有组合}
};
131. 分割回文串
题目链接
文章讲解
class Solution {
public:vector<vector<string>> ans; // 存储所有回文分割结果vector<string> path; // 当前的回文分割路径// 判断字符串是否是回文bool isPalindrome(string& s, int start, int end) {while (start < end) {if (s[start] != s[end]) return false;start++;end--;}return true;}// 回溯函数,递归生成所有回文分割void dfs(string& s, int start) {if (start == s.size()) { // 如果已经分割完所有字符串,加入结果ans.push_back(path);return;}for (int i = start; i < s.size(); i++) {// 如果当前子串是回文if (isPalindrome(s, start, i)) {path.push_back(s.substr(start, i - start + 1)); // 加入子串dfs(s, i + 1); // 递归处理下一个部分path.pop_back(); // 回溯,撤销选择}}}// 主函数vector<vector<string>> partition(string s) {dfs(s, 0); // 从索引0开始进行回溯return ans; // 返回所有回文分割的结果}
};