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

【LeetCode 热题 100】437. 路径总和 III——(解法一)递归递归!

Problem: 437. 路径总和 III
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N^2) (最坏情况), O(N log N) (平均情况)
    • 空间复杂度:O(H),其中 H 是树的高度

整体思路

这段代码旨在解决一个经典的二叉树问题:路径总和 III (Path Sum III)。问题要求计算一棵二叉树中,节点值之和等于目标值 targetSum路径 的数量。这里的“路径”必须是向下的(从父节点到子节点),但它不必从根节点开始,也不必在叶子节点结束。

该算法采用了一种 递归的“分治”思想。它巧妙地将问题分解为三个互不重叠的子问题,在树的每个节点上进行计算:

  1. 问题的分解:对于树中的任意一个节点 node,所有满足条件的路径可以被归为三类:
    a. 路径 必须以 node 为起点
    b. 所有满足条件的路径 完全位于 node 的左子树 中(即路径的起点和终点都在左子树)。
    c. 所有满足条件的路径 完全位于 node 的右子树 中。

  2. 双重递归结构:为了解决这个问题,代码使用了双重递归:

    • 主递归函数 pathSum:这个函数是“分治”的实施者。对于当前节点 root,它的任务是计算上述三类路径的总和。
      • 它通过调用一个辅助函数 dfs(root, targetSum) 来计算第一类路径的数量。
      • 它通过递归调用 pathSum(root.left, targetSum) 来计算第二类路径的数量。
      • 它通过递归调用 pathSum(root.right, targetSum) 来计算第三类路径的数量。
      • 最后将这三者的结果相加,就是以 root 为根的树中所有满足条件的路径总数。
    • 辅助递归函数 dfs:这个函数的目标很专一:计算必须以给定节点 node 为起点的路径中,和为 sum 的路径有多少条。
      • 它通过将 sum 减去当前节点的值,然后带着这个新的“剩余和”继续向其左右子节点递归。
      • 如果在任何一个节点上,“剩余和”恰好等于0,就意味着找到了一条满足条件的路径,计数器加一。

通过这种“主递归遍历每个节点作为潜在起点,辅助递归从该起点向下探索”的模式,算法可以不重不漏地找出所有符合条件的路径。

完整代码

class Solution {/*** 主函数:计算二叉树中路径和等于 targetSum 的路径数量。* @param root 树的根节点* @param targetSum 目标和* @return 满足条件的路径数量*/public int pathSum(TreeNode root, int targetSum) {// 递归的终止条件:如果当前节点为空,则不存在任何路径,返回0。if (root == null) {return 0;}// 分治思想的体现:问题分解为三个部分// 1. 计算以当前 root 节点为起点的路径数量。//    这个任务交由辅助函数 dfs 完成。int pathsFromRoot = dfs(root, targetSum);// 2. 递归地计算在左子树中,所有满足条件的路径数量。//    注意:这些路径的起点和终点都必须在左子树内部。int pathsOnLeft = pathSum(root.left, targetSum);// 3. 递归地计算在右子树中,所有满足条件的路径数量。int pathsOnRight = pathSum(root.right, targetSum);// 最终结果是这三个不相交的路径集合的数量之和。return pathsFromRoot + pathsOnLeft + pathsOnRight;   }/*** 辅助函数:计算以指定节点 node 为起点,路径和为 sum 的路径数量。* @param node 路径的起始节点* @param sum 目标和(在递归过程中表示剩余需要达成的和)* @return 从 node 出发的满足条件的路径数量*/private int dfs(TreeNode node, long sum) {// 递归的终止条件:如果节点为空,说明此路不通,返回0。if (node == null) {return 0;}// 计算包含当前节点后,还需要多少和才能达到目标。// 使用 long 类型是为了防止节点值累加后发生整数溢出。long remainSum = sum - node.val;// 检查当前路径是否正好满足条件。// 如果 remainSum 为 0,说明从起点到当前节点的路径和恰好等于目标和。int cnt = (remainSum == 0) ? 1 : 0;// 继续向下探索:// 递归地在左子树中寻找以 node.left 为延续的路径。cnt += dfs(node.left, remainSum);// 递归地在右子树中寻找以 node.right 为延续的路径。cnt += dfs(node.right, remainSum);// 返回从 node 出发找到的路径总数。return cnt;}
}

时空复杂度

时间复杂度:O(N^2) (最坏情况), O(N log N) (平均情况)

  1. 分析结构pathSum 函数会对树中的每个节点调用一次。假设树有 N 个节点。在 pathSum(node) 的每次调用中,它都会启动一次 dfs(node, ...)
  2. dfs 的开销dfs(node, ...) 会遍历以 node 为根的整个子树。如果这个子树有 k 个节点,那么 dfs 的时间复杂度就是 O(k)。
  3. 总开销:因此,总的时间复杂度可以看作是树中每个节点 u 都作为起点进行了一次深度优先搜索,搜索范围是 u 的子树。
    • 总时间 = Σ (对每个节点 u) O(size_of_subtree(u))
  4. 最坏情况(Skewed Tree,链状树)
    • 如果树退化成一个链表,节点数为 N
    • pathSum 对根节点调用 dfs,耗时 O(N)。
    • 对第二个节点调用 dfs,耗时 O(N-1)。
    • 总时间复杂度为 O(N + (N-1) + … + 1) = O(N^2)
  5. 平均情况(Balanced Tree,平衡二叉树)
    • 对于一棵平衡二叉树,一个节点的子树大小与其深度有关。
    • 每个节点 u 被访问的次数等于其在树中的深度 depth(u)。总的访问次数可以看作是 Σ depth(u),这大致等于 N * log N
    • 因此,在树比较平衡的情况下,时间复杂度为 O(N log N)

空间复杂度:O(H),其中 H 是树的高度

  1. 递归调用栈:该算法的空间复杂度主要由递归调用的深度决定。
  2. pathSumdfs 的关系pathSum 的递归深度和 dfs 的递归深度不会简单相加,因为它们是嵌套调用的。在任一时刻,调用栈的最大深度受限于树的高度 H
  3. 最坏情况(Skewed Tree)
    • 如果树退化成一个链表,树的高度 H = N。此时递归栈的深度会达到 N。空间复杂度为 O(N)
  4. 平均情况(Balanced Tree)
    • 如果树是平衡的,树的高度 H = log N。此时递归栈的深度为 log N。空间复杂度为 O(log N)

综合分析
空间复杂度可以统一表示为 O(H),其中 H 是树的高度。

http://www.lryc.cn/news/593450.html

相关文章:

  • CCF编程能力等级认证GESP—C++7级—20250628
  • STM32_Hal库学习ADC
  • IntelliJ IDEA中Mybatis的xml文件报错解决
  • SSM框架——注入类型
  • aws(学习笔记第四十九课) ECS集中练习(1)
  • Streamlit 官翻 5 - 部署、社区云 Deploy
  • Python绘制数据(三)
  • Matplotlib 30分钟精通
  • 人该怎样活着呢?55
  • Windows11下编译好的opencv4.8-mingw,可下载后直接用
  • Apache Kafka 学习笔记
  • 详细阐述 TCP、UDP、ICMPv4 和 ICMPv6 协议-以及防火墙端口原理优雅草卓伊凡
  • Python高级数据类型:字典(Dictionary)
  • Datawhale 7月学习
  • RK3568 Linux驱动学习——SDK安装编译
  • Oracle为什么需要临时表?——让数据处理更灵活
  • DAY 18 推断聚类后簇的类型
  • 【Project】kafka+flume+davinci广告点击实时分析系统
  • MySQL(145)如何升级MySQL版本?
  • 在服务器(ECS)部署 MySQL 操作流程
  • 基于单片机宠物喂食器/智能宠物窝/智能饲养
  • 手撕Spring底层系列之:注解驱动的魔力与实现内幕
  • Spring AI 1.0版本 + 千问大模型之 文本记忆对话
  • 基于单片机病床呼叫系统/床位呼叫系统
  • C#操作WPS表格
  • 大模型军备竞赛升级!Grok 4 携 “多智能体内生化” 破局,重构 AI 算力与 Agent 2.0 时代
  • 张 关于大语言模型(LLM)置信度研究的经典与前沿论文 :温度缩放;语义熵;自一致性;事实与反思;检索增强;黑盒引导;
  • [MySQL基础3] 数据控制语言DCL和MySQL中的常用函数
  • 一个基于阿里云的C端Java服务的整体项目架构
  • 阿里云ssl证书自动安装及续订(acme)