hot100 二叉树中的最大路径和(124)

发布时间:2026/7/13 17:47:00
hot100 二叉树中的最大路径和(124) 本题采用树形动态规划与后序遍历递归算法又称“路径桥接与贡献度剪枝法”解决二叉树中的最大路径和求解问题。其核心本质是将全局任意路径最大和的搜索转化为自底向上测算每个节点作为“路径最高转折点”的局部最大值并利用非负贡献度剪枝策略过滤负面数据。当前提供的源码实现了在时间复杂度 O(n) 和额外空间复杂度 O(h)其中 h 为树的高度条件下的全局状态寻优最终走向是精准定位并返回全树中节点值之和的最大值。一、 问题本质与数据模型根据题目定义二叉树中的一条合法路径在拓扑结构上具有独特的几何局限一条路径最多只能拥有一个“最高转折点”即双向延伸的顶点其余节点在路径中只能作为单向延伸的链条。对于树中的任意一个节点 root它在路径构造中必然扮演双重角色全局/局部路径的转折点路径同时穿过其左子树、自身以及右子树。一旦节点充当了这种横向桥接的转折点该路径的两个端点都已深入到子树中无法再向上延伸对接父节点。这构成了一个潜在的全局最大路径和候选者。向父节点提供单向延伸的贡献分支路径从父节点进入当前节点并选择其左子树或右子树中较深的一侧继续向下延伸。由于树节点的值包含负数盲目叠加会导致路径和减小。因此算法引入了“非负贡献剪枝模型”。如果某个子树测算出的最大单向延伸收益为负数则对于当前节点而言连接该子树只会拉低总收益。此时应果断触发剪枝将该子树的贡献度强行截断为 0。二、 算法演进对比在求解二叉树最大路径和的场景中树形动态规划后序回溯法在时空资源的利用率上达到了平衡极限解法名称时间复杂度空间复杂度核心原理物理瓶颈 / 缺陷双重递归暴力枚举O(n^2)O(h)遍历每个节点作为最高转折点对每个节点独立向下进行双向 DFS 深度探测节点被重复访问多次计算高度冗余时间效率极低树形动规后序回溯当前解法O(n)O(h)一次后序遍历中同时完成“子树单向贡献测算”与“全局转折路径最大值更新”依赖成员变量维护全局最大值状态极度倾斜树下调用栈深迭代自底向上模拟O(n)O(n)显式维护双栈或指针序列模拟后序回溯手动装配各个节点的贡献状态状态机的物理维护与分支判定极其复杂编码可读性极低三、 核心分支控制逻辑与决策证明当前源码的控制流完全依赖于私有递归函数dfs(root)内的后序回溯与全局类成员变量ans的动态更新其内部决策分支证明如下1. 基准退出分支if (root null)执行直接返回 0。物理意义当前探测路径已越过叶子节点触及虚拟空边界。空节点不具备任何物理数值其路径收益贡献精确为 0。2. 全局转折状态更新ans Math.max(lRes rRes root.val, ans);执行以当前节点为最高转折点桥接左右子树构建一条闭合路径并尝试刷新全局最大值 ans。数学证明由于底部的返回语句带有剪枝保护此处拿到的lRes和rRes必定大于或等于 0。因此lRes rRes root.val物理上完美涵盖了四种情况仅选根节点左右均负贡献被剪枝为 0、选根加左、选根加右、根左右全选。这确保了以当前节点为顶点的最大局部路径和被完全捕获。3. 单向分支收益回溯return Math.max(Math.max(lRes, rRes) root.val, 0);执行向父节点返回当前节点能提供的最大单向延伸路径和若为负则直接清零。数学证明当前节点若要和父节点无缝连接在拓扑上只能在左子树lRes和右子树rRes中挑选一条收益更大的单向链路进行延伸即Math.max(lRes, rRes) root.val。如果此单向链路的总收益依然为负则说明对于上层父节点而言连接当前节点只会降低总和因此通过外层Math.max(..., 0)直接将其贡献清零向上传递 0。四、 算法执行状态机步进示例以输入二叉树root [-10, 9, 20, null, null, 15, 7]为例规模 n 5树高 h 3递归调用栈及全局状态机变迁过程如下表所示步骤当前访问节点值左右子树返回的有效单向收益 (lRes, rRes)当前转折总和 (lRes rRes root.val)全局最大值 ans 更新状态向上层回溯的单向贡献值初始---Integer.MIN_VALUE-19(0, 0)0 0 9 9max(9, MIN) 9max(9, 0) 9215(0, 0)0 0 15 15max(15, 9) 15max(15, 0) 1537(0, 0)0 0 7 7max(7, 15) 15max(7, 0) 7420(15, 7)15 7 20 42max(42, 15) 42max(35, 0) 355-10(9, 35)9 35 (-10) 34max(34, 42) 42max(25, 0) 25五、 源码实现/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val val; * this.left left; * this.right right; * } * } */ class Solution { public int maxPathSum(TreeNode root) { // 启动深度优先搜索自底向上驱动状态机 dfs(root); // 返回全局捕获的最大路径和 return ans; } // 初始化全局最大值变量为整型最小值确保能被树中的任意路径和正确刷新 private int ans Integer.MIN_VALUE; private int dfs(TreeNode root) { // 基准收敛条件触及空节点边界返回物理贡献度 0 if (root null) { return 0; } // 分治递归后序遍历模式先索取左子树向上的最大非负单向贡献 int lRes dfs(root.left); // 分治递归后序遍历模式再索取右子树向上的最大非负单向贡献 int rRes dfs(root.right); // 核心控制以当前节点为最高桥接转折点尝试组合左右链路刷新全局最大值 ans Math.max(lRes rRes root.val, ans); // 状态回溯选择左右分支中的较大者与当前节点值叠加若整体为负则触发零值剪枝 return Math.max(Math.max(lRes, rRes) root.val, 0); } }六、 复杂度分析1. 时间复杂度O(n)分析算法采用严格的后序遍历深度优先搜索对二叉树中的每一个物理节点进行且仅进行一次访问。在每个节点内部执行的运算三次Math.max取最值操作、基础加法均为常数阶操作 O(1)。若树中包含 n 个节点总的计算步数与节点总量 n 呈严格的线性正比关系。结论时间复杂度为 O(n)在未已知最优路径局部特征的情况下已达到理论计算下界。2. 空间复杂度O(h)分析算法未使用任何与输入规模成正比的外部独立数据结构。其内存空间的动态开销完全由隐式的方法调用栈深度决定。调用栈的物理深度与二叉树的高度 h 保持同步。在最坏情况下二叉树退化为单链表树高 h 等于 n空间复杂度表现为 O(n)在最好情况下完全平衡二叉树树高被压制在对数层级空间复杂度为 O(log n)。结论全局额外空间复杂度定性为 O(h)。