maxPathSum不能直接返回左右子树最大路径和之和,因为路径必须连续且最多一个拐点;真正能向上贡献的只有以当前节点为端点的最大单向路径和,而全局最大值由当前节点值加左右非负单向收益得到。

为什么 maxPathSum 不能直接返回左右子树最大路径和之和
因为「路径」在二叉树中必须是连续的、不重复经过节点的节点序列,且最多只能有一个“拐点”(即路径从左子树上来、经过当前节点、再往下走到右子树)。一旦你把左右子树各自的最大路径和相加,就隐含允许路径分叉——这在单条路径中是非法的。
真正能向上贡献的,只有以当前节点为端点的一条单向路径:即 node->val 加上「左或右子树中能提供的最大单向收益」(且该收益必须 ≥ 0,否则不如不走)。
所以递归函数要拆成两个职责:
- 返回值:以当前节点为起点向下延伸的**最大单向路径和**(供父节点拼接用)
- 全局更新:
max_sum记录所有可能的「经过当前节点的完整路径和」——即node->val + max(0, left_gain) + max(0, right_gain)
maxPathSum 递归函数里如何处理负收益子树
子树返回的单向路径和可能是负数(比如全是负节点),这时候父节点如果硬把它拉进来,反而会拉低总和。所以必须做截断:只取 max(0, gain)。
立即学习“C++免费学习笔记(深入)”;
示例:当前节点值为 10,左子树返回 -5,右子树返回 -8。那么经过它的最优路径就是它自己:10;而不是 10 + (-5) + (-8) = -3。
关键代码逻辑如下:
int left_gain = max(0, maxGain(node->left)); int right_gain = max(0, maxGain(node->right)); int price_newpath = node->val + left_gain + right_gain; max_sum = max(max_sum, price_newpath); return node->val + max(left_gain, right_gain);
初始化 max_sum 为什么要用 INT_MIN 而不是 0
因为树中所有节点可能都是负数,比如 [-3, -2, -1],此时最大路径和就是 -1(单个叶子节点)。如果初始化为 0,最终结果会错误地卡在 0,无法更新。
更稳妥的做法是在进入递归前设为最小整数:
int max_sum = INT_MIN; maxGain(root);
注意:maxGain 是辅助递归函数名,它不负责全局答案,只负责计算单向收益并触发更新。
递归终止时返回 0 还是 INT_MIN?
返回 0 是对的。空节点不提供任何路径收益,但也不应拖累父节点——返回负数会让父节点的 max(0, gain) 截断失效,而返回 0 刚好被 max(0, ...) 吞掉,符合“不选”的语义。
错误写法示例(导致结果偏小):
if (!node) return INT_MIN; // ❌ 父节点 max(0, INT_MIN) → 0,看似一样,但若用加法链式传播会出错
正确写法:
if (!node) return 0;
这个 0 不是“有收益”,而是“无贡献但可安全忽略”。路径收益计算里最易被忽略的,恰恰是空节点的语义一致性——它不是异常,而是路径终止的自然边界。


















