leetcode回溯算法(39.组合总和)

cpp 复制代码
class Solution {
private:
    vector<vector<int>> result; // 存储所有符合条件的组合
    vector<int> path; // 当前搜索路径(当前组合)
    
    // 回溯函数
    // candidates: 候选数字数组
    // target: 目标总和
    // sum: 当前路径中数字的总和
    // startIndex: 当前搜索开始位置(防止重复组合)
    void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
        // 终止条件1:当前和已经超过目标值
        if (sum > target) {
            return; // 直接返回,不再继续搜索
        }
        
        // 终止条件2:当前和等于目标值
        if (sum == target) {
            result.push_back(path); // 找到有效组合,加入结果集
            return; // 返回上一层
        }

        // 从startIndex开始遍历候选数字
        for (int i = startIndex; i < candidates.size(); i++) {
            sum += candidates[i]; // 选择当前数字,更新总和
            path.push_back(candidates[i]); // 将当前数字加入路径
            
            // 递归调用,注意这里传的是 i 而不是 i+1
            // 因为允许重复使用同一个数字
            backtracking(candidates, target, sum, i);
            
            // 回溯:撤销选择
            sum -= candidates[i]; // 从总和中减去当前数字
            path.pop_back(); // 从路径中移除当前数字
        }
    }
    
public:
    // 主函数:组合总和
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        result.clear(); // 清空结果集
        path.clear(); // 清空当前路径
        // 从第0个位置开始回溯搜索
        backtracking(candidates, target, 0, 0);
        return result; // 返回所有符合条件的组合
    }
};

例子candidates = [2,3,6,7], target = 7

初始状态:

复制代码
result = []
path = []
sum = 0
startIndex = 0

第一层递归:backtracking([2,3,6,7], 7, 0, 0)

cpp 复制代码
for (int i = startIndex; i < candidates.size(); i++) {
        sum += candidates[i];
        path.push_back(candidates[i]);
        backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
复制代码
不满足前面if条件
for循环,开始 i=0
sum = sum + candidates[0] = 0 + 2 = 2
path = [2]
进入递归...backtrackint([2,3,6,7], 7, 2, 0)

第二层递归:backtracking([2,3,6,7], 7, 2, 0)

复制代码
不满足前面if条件
for循环,开始 i=0
sum = sum + candidates[0] = 2 + 2 = 4
path = [2,2]
进入递归...backtracking([2,3,6,7], 7, 4, 0)

第三层递归:backtracking([2,3,6,7], 7, 4, 0)

复制代码
for循环,开始 i=0
sum = sum + candidates[0] = 4 + 2 = 6
path = [2,2,2]
进入递归...backtracking([2,3,6,7], 7, 6, 0)

第四层递归:backtracking([2,3,6,7], 7, 6, 0)

复制代码
for循环,开始 i=0
cpp 复制代码
       for (int i = startIndex; i < candidates.size(); i++) {
            sum += candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
复制代码
// 选择 candidates[0] = 2
sum += candidates[i];    // sum = 6 + 2 = 8
path.push_back(candidates[i]);  // path = [2,2,2,2]
backtracking(candidates, target, sum, i);
// 参数:candidates=[2,3,6,7], target=7, sum=8, i=0

进入第五层递归(由于 sum=8 > target=7

复制代码
void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
    if (sum > target) {  // 8 > 7? true
        return;  // 立即返回
    }
    // ... 不会执行后续代码
}

回溯(撤销选择)

复制代码
// 返回到第四层递归,继续执行
sum -= candidates[i];    // sum = 8 - 2 = 6
path.pop_back();         // path = [2,2,2]
// 循环继续...
复制代码
for循环,开始 i=1
cpp 复制代码
       for (int i = startIndex; i < candidates.size(); i++) {
            sum += candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
复制代码
// 选择 candidates[1] = 3
sum += candidates[i];    // sum = 6 + 3 = 9
path.push_back(candidates[i]);  // path = [2,2,2,3]
backtracking(candidates, target, sum, i);
// 参数:candidates=[2,3,6,7], target=7, sum=9, i=0

.........

.........

.........

相关推荐
地平线开发者10 小时前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮10 小时前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者11 小时前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考11 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx14 小时前
CART决策树基本原理
算法·机器学习
Wect15 小时前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
颜酱15 小时前
单调队列:滑动窗口极值问题的最优解(通用模板版)
javascript·后端·算法
Gorway1 天前
解析残差网络 (ResNet)
算法
拖拉斯旋风1 天前
LeetCode 经典算法题解析:优先队列与广度优先搜索的巧妙应用
算法
Wect1 天前
LeetCode 207. 课程表:两种解法(BFS+DFS)详细解析
前端·算法·typescript