因为递归函数只能返回单向路径(向下延伸、不可分叉),而最大路径可能拐弯(左→根→右),故需分离逻辑:返回值为单侧最大贡献(供父节点拼接),全局更新用左右贡献加当前节点值;空节点返回0,负子树被max(0,·)截断,确保路径可中断且不误删单节点解。

为什么maxPathSum不能直接返回“整条路径”的和?
因为二叉树中路径可以拐弯(从左子树经根到右子树),但递归函数每次只能向上交出一条“单向路径”——即从当前节点向下延伸、不回头的路径。所以maxPathSum必须拆成两个逻辑:一个是供父节点拼接的「单侧最大贡献值」,另一个是全局更新用的「经过当前节点的最大路径和」。
常见错误是让递归函数同时承担两种语义,结果在负数节点或空子树时漏判边界,导致路径被意外截断或重复累加。
- 空节点贡献值必须返回
0(不是INT_MIN),否则父节点无法安全做left_gain + right_gain + root->val - 单侧贡献值要和
0取max,意味着“如果子树拖后腿,就弃掉它”,这是路径可中断的关键 - 全局答案更新必须放在递归内部,不能只依赖返回值
int maxGain(TreeNode* node) 的返回值到底代表什么?
它代表:以 node 为起点,**向下延伸**(最多到叶子)所能获得的最大路径和;该路径必须连续、不可分叉,且允许为空(即返回 0)。
这个定义决定了它的计算方式:
- 先递归算出
left_gain = maxGain(node->left)和right_gain = maxGain(node->right) - 再取
max(0, left_gain)和max(0, right_gain),过滤掉负收益子树 - 最后返回
node->val + max(left_gain, right_gain)—— 注意是max,不是+,因为只能选一侧向上连
而真正用于更新全局答案的,是 node->val + left_gain + right_gain(此时左右都已与 0 取过 max),这才是“经过本节点的完整路径”。
负数节点怎么处理?会不会导致路径被错误截断?
不会截断,但会触发“放弃子树”逻辑。比如节点值为 -5,左子树贡献 -2,右子树贡献 -10,那么:
left_gain = max(0, -2) = 0right_gain = max(0, -10) = 0- 该节点向上贡献为
-5 + max(0, 0) = -5(仍可能被父节点舍弃) - 但经过它的路径和是
-5 + 0 + 0 = -5,仍参与全局比较
关键点在于:是否“放弃子树”由子树贡献是否为正决定,而不是当前节点是否为负。哪怕当前节点是负的,只要左右子树有正收益,它依然能成为路径中转站。
LeetCode 测试用例 [−3] 为什么会返回 −3?
因为题目允许路径只含一个节点。当只有根节点时:
-
left_gain = 0,right_gain = 0(空子树) - 经过根的路径和 =
-3 + 0 + 0 = -3 - 该节点向上贡献 =
-3 + max(0, 0) = -3
所以全局最大值就是 -3。很多人误以为“路径至少两个节点”,其实不然;这也是为什么初始化 max_sum 不能设为 0,而应设为 INT_MIN 或直接用第一个节点值。
实际写的时候,最稳妥的是把 max_sum 声明为成员变量或引用传入,在首次进入 maxGain 时就更新,避免初值陷阱。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











