maxPathSum不能直接返回子树最大路径和,因为路径可跨根节点,而递归返回值仅表示从当前节点向下的单向路径;需用辅助函数gain计算单向最大收益(负则截断为0),同时用全局变量res更新跨左右子树的最大路径和。

为什么 maxPathSum 不能直接返回子树最大路径和?
因为路径可以「跨过根节点」,但递归返回值只能代表「从当前节点向下延伸的单向路径」。如果让 maxPathSum 同时承担「更新全局答案」和「返回单向最大收益」两个职责,逻辑会混在一起,容易漏掉跨左右子树的路径组合。
正确做法是用一个辅助函数(比如叫 gain)只干一件事:计算以当前节点为起点、向下走(最多到叶子)能带来的最大贡献值(即「节点收益」),且该值必须 ≥ 0(负收益不如不走,可截断为 0)。
-
gain(node)返回的是node->val + max(0, gain(node->left), gain(node->right)) - 每次进入
gain,都用node->val + max(0, gain(node->left)) + max(0, gain(node->right))尝试更新全局最大路径和 - 注意:空节点返回 0,不是 INT_MIN —— 因为「不选」本身就是一种合法选择
如何处理负数节点导致的路径截断?
路径不是必须包含叶子,也不是必须拉满长度;只要连续、不重复经过节点,就可以随时终止。所以当某子树的 gain 为负时,向上返回 0,相当于告诉父节点:“别往我这走,没收益”。
- 例如节点值为 -5,左右子树
gain分别为 -2 和 -1 → 总贡献 = -5 + 0 + 0 = -5,这是合法路径(单节点) - 但如果父节点是 1,则 1 + max(0, -5) = 1,说明父节点宁可抛弃 -5 这棵子树
- 因此判断是否截断,只看子树
gain是否 > 0,而不是看节点本身正负
int& res 引用传参 vs 全局变量,哪个更安全?
用引用参数比全局变量更可控,尤其在多测试用例或并发调用场景下。但要注意:不能把局部变量地址传进去,必须确保 res 生命周期覆盖整个递归过程。
- 推荐写法:
int res = INT_MIN; dfs(root, res); return res;,其中dfs是带int& res的辅助函数 - 避免写成
static int res—— 多次调用会残留上一次结果 - 如果用类封装,可将
res设为成员变量,但需在入口函数中重置,否则 LeetCode 连续运行会出错
LeetCode 提交时常见的 WA 原因
多数失败不是算法错,而是边界没兜住。最典型的是空树、单节点、全负数三种情况。
- 空树:输入
root == nullptr,gain返回 0,但全局res初始值要是INT_MIN,否则单负节点(如 [-3])会误判为 0 - 全负数:路径只能选一个节点,所以答案就是最大那个负数,不是 0 —— 所以
res更新式里不能强制加max(0, ...),而要原样算node->val + left_gain + right_gain - 忘记更新
res:只写了return,没在递归中间做res = max(res, ...),就会永远返回初始值
最易忽略的一点:路径和计算中,左右子树的 gain 是独立截断的,但拼成完整路径时,它们的负值要被真实计入——也就是说,截断只发生在「向上返回」时,不发生在「当前层路径合成」时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











