最大路径和通过每个节点返回最大单边贡献并用全局变量记录以该节点为顶点的完整路径和来高效求解;关键在于用max(0, left_gain)和max(0, right_gain)截断负增益,空节点返回0,res在递归中实时更新。

直接说结论:最大路径和不是靠“遍历所有路径”算出来的,而是靠每个节点向上返回“我能贡献的最大单边路径和”,同时用全局变量捕获“以我为顶点的完整路径和”——这才是递归解法真正高效的原因。
为什么不能直接递归求“路径和”?
因为路径可以跨左右子树、不经过根、也不必到叶子。如果写一个函数 int pathSum(TreeNode* node) 试图直接返回“以 node 为起点的最大路径和”,它无法区分:是只走一边(可继续向上拼接),还是必须连通两边(已成完整路径,不能再往上延)。强行拆分逻辑会重复计算、边界混乱,且无法统一更新全局最优解。
真正的突破口在于:把问题拆成两个角色:
- 每个节点向父节点报告:“我最多能帮你加多少”(即
max(left_gain, right_gain) + node->val,且负收益截断为 0) - 每个节点顺便算一下:“如果把我当最高点,左右都拉进来,当前路径和是多少”(即
left_gain + right_gain + node->val),并用全局变量res记录见过的最大值
max(0, ...) 不是可选项,是保命操作
节点值可能为负,若某侧子树返回负的“最大贡献”,接上去只会拉低总和。所以必须用 max(0, left_gain) 和 max(0, right_gain) 截断——这保证了向上返回的永远是非负“增益”,也使得“单边路径”定义清晰、可组合。
常见错误现象:
- 漏掉
max(0, ...),遇到[-3]或[-2,-1]直接返回负数,导致res被错误更新为负值 - 只对返回值截断,但没对参与
left_gain + right_gain + val计算的部分截断,造成路径和被负值污染 - 把截断逻辑写成
max(-1e9, ...)等无效写法,起不到作用
全局变量 res 必须在递归中实时更新
递归函数本身只负责“上传单边收益”,它不保存历史最大值。如果不设全局或引用传参的 res,就只能靠返回值传递,而返回值已被占用为“单边路径和”,无处安放“跨左右的完整路径和”。
实操建议:
- 声明
int res = INT_MIN在类内或作为函数参数引用(如int& res) - 更新时机必须在左右子树递归调用之后、返回前:即
res = max(res, left + right + node->val) - 不要试图在 return 语句里同时更新
res,可读性差且易错;分开两行更安全
边界处理:空节点必须返回 0
这是整个递归结构稳定的基石。如果写成 return -1 或 return INT_MIN,会导致 max(0, ...) 失效(比如 max(0, INT_MIN) 还是 INT_MIN),后续计算全崩。
正确写法只有一行:if (!node) return 0;。不需要额外判断 node->left == nullptr 等分支——递归自然覆盖所有子树,空指针由最上层拦截。
容易被忽略的是:这个 0 不代表“没有路径”,而是代表“这条支路不提供任何正向增益”,它和 max(0, ...) 形成闭环,共同支撑起“收益最大化”的语义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











