最大路径和必须用后序遍历+全局变量更新,因递归返回值仅表示以当前节点为起点的单向最大路径和,无法表达跨左右子树的“V型”路径;需用left_gain+right_gain+root->val实时更新全局最大值,并对负收益提前截断为0。

最大路径和必须用后序遍历 + 全局变量更新,不能靠递归返回值直接得出答案。 因为每个节点能向上提供的只有一条单向路径(左或右),但真正的最大路径很可能跨左右子树(如 15→20→7),这个“V型”路径无法作为返回值传给父节点,只能在本地用 left_gain + right_gain + root->val 算出来并更新全局最大值。
为什么递归函数返回值 ≠ 最大路径和
递归函数的语义是「以当前节点为起点、向下延伸的最大单向路径和」,它服务于父节点拼接,不是最终答案。如果你写成 return max(left, right) + root->val 并指望这个值就是答案,就漏掉了所有跨子树路径。例如节点值为 20、左子树贡献 15、右子树贡献 7:max(15, 7) + 20 == 35 是返回值,但真正最大路径是 15 + 20 + 7 == 42,必须单独计算并更新。
- 返回值只能带一条分支上去,否则父节点会分叉,违反路径定义
-
left_gain + right_gain + root->val这个值永远不返回,只用于更新全局变量 - 函数签名应为
int dfs(TreeNode* root),不要试图让它同时承担两个角色
max(0, left_gain) 和 max(0, right_gain) 必须分别截断
负子树收益必须在参与拼接前就截断,否则会污染 left_gain + right_gain + root->val 的计算。常见错误是只在返回值里做 max(0, ...),却在拼完整路径时仍用原始负值——比如左子树返回 -5,你不截断就直接加进去,root->val + (-5) + right_gain 就错了。
- 正确做法:先调
dfs(root->left)得到原始left_gain,再立即int l = max(0, left_gain) - 同理处理右子树:
int r = max(0, right_gain) - 然后用
root->val + l + r更新全局最大值 - 返回值是
root->val + max(l, r),也建议再套一层max(0, ...)防止负数上传
空节点返回 0 而不是 INT_MIN
空节点没有路径可言,也不该拖累父节点计算。返回 INT_MIN 会导致 root->val + INT_MIN 溢出,或让 max(0, INT_MIN) 失效(某些平台下行为未定义)。更重要的是,语义混乱:0 表示“无贡献”,刚好被 max(0, gain) 吞掉,符合“不选这条分支”的直觉。
立即学习“C++免费学习笔记(深入)”;
- 所有递归入口第一行必须是
if (!root) return 0; - 全负树(如
[-3,-2,-1])依赖这个逻辑:叶子节点返回自身负值,上层取max(0, -3) == 0,最终root->val + 0 + 0把 -1 记入全局最大值 - 若误写成
if (!root) return INT_MIN;,轻则结果错,重则运行时崩溃
最易被忽略的点是:你手里始终有两个数(左收益、右收益),但只能把其中一个喂给父节点,却必须用两个一起算当前层的全局最优。这个职责割裂不是设计缺陷,而是路径定义本身决定的——路径允许一个拐点,但不允许分叉。


















