当前位置: 首页 > news >正文

完整教程:leetcode算法(112.路径总和)

class Solution {
private:// 递归遍历函数,cur表示当前节点,count表示当前还需要凑足的和bool traversal(TreeNode* cur, int count) {// 如果当前节点是叶子节点,并且count已经减到0,说明找到了一条路径if (cur->left==NULL && cur->right==NULL && count == 0) return true;// 如果当前节点是叶子节点但count不为0,说明这条路径和不符合要求if (cur->left==NULL && cur->right==NULL && count!=0) return false;// 如果存在左子节点if (cur->left) { // 左count -= cur->left->val; // 递归前:将左子节点的值从count中减去(进入路径)if (traversal(cur->left, count)) return true; // 递归进入左子树count += cur->left->val; // 回溯:恢复count的值(撤销选择)}// 如果存在右子节点if (cur->right) { // 右count -= cur->right->val; // 递归前:将右子节点的值从count中减去(进入路径)if (traversal(cur->right, count)) return true; // 递归进入右子树count += cur->right->val; // 回溯:恢复count的值(撤销选择)}// 左右子树都没有找到符合条件的路径return false;}
public:// 判断是否存在从根节点到叶子节点的路径,其节点值之和等于sumbool hasPathSum(TreeNode* root, int sum) {// 处理空树的情况if (root == NULL) return false;// 调用递归函数,初始时已经包含了根节点的值(sum - root->val)return traversal(root, sum - root->val);}
};
举例: 5/ \4   8/   / \11  13  4/  \      \7    2      1

步骤1:主函数调用

hasPathSum(root, 22)
  • root != NULL,所以继续

  • 调用 traversal(root, 22 - 5),即 traversal(root, 17)

    • 初始 cur = 节点5 count = 17

步骤2:进入 traversal(节点5, 17)

  • 节点5不是叶子节点(有左右子节点)

  • 先处理左子树:

if (cur->left) { // 节点5有左子节点4count -= cur->left->val;  // count = 17 - 4 = 13if (traversal(cur->left, 13)) return true;// 递归进入节点4
}

步骤3:进入 traversal(节点4, 13)

  • 节点4不是叶子节点(有左子节点11)

  • 处理左子树:

if (cur->left) { // 节点4有左子节点11count -= cur->left->val;  // count = 13 - 11 = 2if (traversal(cur->left, 2)) return true;  // 递归进入节点11// 注意:这里进入递归,后面可能找到路径直接返回true
}

    步骤4:进入 traversal(节点11, 2)

    if (cur->left) { // 节点11有左子节点7count -= cur->left->val;  // count = 2 - 7 = -5if (traversal(cur->left, -5)) return true;  // 递归进入节点7
    }

    步骤5:进入 traversal(节点7, -5)

    • 节点7是叶子节点(左右子节点都为空)

    • 检查条件:

    if (cur->left==NULL && cur->right==NULL && count == 0)  // false,因为count = -5 ≠ 0
    if (cur->left==NULL && cur->right==NULL && count != 0) return false;
    // 满足条件,返回false
    • 返回 false 到步骤4

    步骤6:回到 traversal(节点11, 2)

    // 左子树递归结束,返回false
    // 所以继续将 7 加上
    count += cur->left->val;  // count = -5 + 7 = 2(回溯)
    // 现在处理右子树
    if (cur->right) { // 节点11有右子节点2count -= cur->right->val;  // count = 2 - 2 = 0if (traversal(cur->right, 0)) return true;  // 递归进入节点2
    }

    步骤7:进入 traversal(节点2, 0)

    • 节点2是叶子节点

    • 检查条件:

    if (cur->left==NULL && cur->right==NULL && count == 0)
    // 完全满足!返回true
    • 返回 true 到步骤6

    步骤8:回到 traversal(节点11, 2)

    if (traversal(cur->right, 0)) return true;  // 这个调用返回了true
    // 所以直接返回true,不再执行后面的回溯
    • 返回 true 到步骤3

    步骤9:回到 traversal(节点4, 13)

    if (traversal(cur->left, 2)) return true;  // 这个调用返回了true
    // 直接返回true
    • 返回 true 到步骤2

    步骤10:回到 traversal(节点5, 17)

    if (traversal(cur->left, 13)) return true;  // 这个调用返回了true
    // 直接返回true,不再处理右子树
    • 返回 true 到步骤1

    步骤11:主函数

    return traversal(root, sum - root->val);  // 返回true
    • 最终结果为 true

    开始: 节点5, count=17
    ├─ 进入左子节点4: count=13
    │   ├─ 进入左子节点11: count=2
    │   │   ├─ 进入左子节点7: count=-5 → 不是叶子节点or count≠0 → false ⇠
    │   │   └─ 进入右子节点2: count=0 → 叶子节点且count=0 → true ✓
    │   │       找到路径: 5→4→11→2
    │   └─ 返回true ⇠
    └─ 返回true ⇠

    为什么需要最后(return false)返回false?

    1/ \2   3          targetSum = 5

    步骤1:主函数调用

    hasPathSum(root, 5)
    • root != NULL,继续

    • 调用 traversal(root, 5 - 1),即 traversal(节点1, 4)

      • cur = 节点1count = 4

    步骤2:进入 traversal(节点1, 4)

    • 节点1不是叶子节点(有左右子节点2和3)

    • 先处理左子树:

    if(cur->left) {  // 节点1有左子节点2,truecount -= cur->left->val;  // count = 4 - 2 = 2if(traversal(cur->left, 2)) return true;  // 递归进入节点2// 等待递归结果...
    }

    步骤3:进入 traversal(节点2, 2)

    • 节点2是叶子节点(左右子节点都为空)

    • 检查条件:

    if(cur->left==NULL && cur->right==NULL && count!=0)  // count=2≠0return false;// 返回false
    • 返回 false 到步骤2

    步骤4:回到 traversal(节点1, 4)

    // 左子树递归返回false
    count += cur->left->val;  // count = 2 + 2 = 4(回溯)
    // 继续处理右子树
    if(cur->right) {  // 节点1有右子节点3,truecount -= cur->right->val;  // count = 4 - 3 = 1if(traversal(cur->right, 1)) return true;  // 递归进入节点3// 等待递归结果...
    }

    步骤5:进入 traversal(节点3, 1)

    • 节点3是叶子节点

    • 检查条件:

    if(cur->left==NULL && cur->right==NULL && count!=0)  // count=1≠0return false;// 返回false
    • 返回 false 到步骤4

    步骤6:回到 traversal(节点1, 4)

    // 右子树递归返回false
    count += cur->right->val;  // count = 1 + 3 = 4(回溯)
    // 现在函数执行到这里,需要返回值...
    // 问题所在:你的代码缺少 return false; 语句!

    这就是问题!
    函数执行到这里应该返回 false,因为左右子树都没有找到路径,但代码要有返回语句return false。

    return false;  // 左右子树都没有找到路径

    http://www.jsqmd.com/news/379607/

    相关文章:

  • 使用Qwen Code的Skills能力重塑工作流 - yi
  • 大数据ETL工具比较:Sqoop vs Flume vs Kafka
  • Django 中间件
  • temperature定义与使用
  • Google API 教程
  • AI编程工具在高可用架构设计中的应用:从故障注入到灾备方案生成实战
  • 视频转换器HD Video Converter Factory 28.6 便携版
  • XML Schema 复合空元素
  • 2001-2024年上市公司媒体关注度数据+Stata代码
  • 必看!2026年琼海海鲜推荐榜单,探索高性价比家庭聚餐海鲜店与知名夜宵选择
  • 企业AI伦理准则制定中的跨部门协作:AI应用架构师的协调技巧
  • 6大方法教你禁止windows11自动更新,windows自动更新怎么关闭,有效阻止关闭win11更新
  • 把Kindle变成电子表!
  • Turnitin AI率爆表怎么办?揭秘网易有道“学术猹”的官方解决方案 - 品牌观察员小捷
  • Windows优化大师,Windows系统管理工具V9.53绿色优化版,附带实用工具箱,已调整功能优化,windows系统优化管理工具
  • Ruby 条件判断
  • 欧洲医药健康行业招聘数据集:41093条职位记录的全景分析与职业发展应用价值-涵盖了从临床研究、制药销售到医疗器械监管等全产业链的职位信息-人力资源研究、行业发展分析和人才市场预测
  • 法语年鉴数据集-语言学研究、教育资源开发、历史文献分析以及自然语言处理算法训练-深入分析语言演变、教育趋势以及学术内容-法语相关专业的毕业设计
  • 睡前讲一段docker编译镜像的故事
  • 论文降重避坑指南:如何确保 AI 率降至 10% 且不被收录? - 品牌观察员小捷
  • QT UDP网络编程
  • Open-AutoGLM项目实战:在Android设备上构建自动操作与ADB键盘控制
  • 拒绝论文“被收录”风险:2026年最安全的论文降AI率平台深度解析 - 品牌观察员小捷
  • 2026年AIGC痕迹消除与降重实测:为何网易有道“学术猹”能成为行业标杆? - 品牌观察员小捷
  • 《从程序员到CTO沟通说话的力量:技术人有效说服他人的沟通策略与技巧》1
  • 现代C++实现AVL树
  • 西门子数控6FC5373-0AA00-0AA2模块故障代码维修
  • 计算机Java毕设实战-基于web的动物救助网站【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 《CF708E Student‘s Camp》
  • 【课程设计/毕业设计】基于web的动物救助网站【附源码、数据库、万字文档】