C++递归解maxPathSum的核心是每个节点同时计算单侧最大贡献(供父节点使用)和以自身为拐点的完整路径和(更新全局答案),必须用后序遍历+全局变量,因需先得子树结果再合成,且拐点路径不可向上传递。

直接说结论:C++ 里用递归解 maxPathSum,核心不是“找路径”,而是让每个节点干两件事——向上报告自己能提供的单侧最大贡献(只能走左或右),同时用左右贡献拼出以自己为“拐点”的完整路径和,更新全局答案。漏掉任一环节都会错。
为什么必须用后序遍历 + 全局变量
因为要先知道左右子树的最优单侧贡献,才能算当前节点的拐点路径和;而拐点路径和不能返回给父节点(父节点不能同时接两条向下分支),所以必须在本地记录。这意味着:
-
dfs函数返回值 ≠ 全局答案,它只返回node->val + max(0, max(left_contribution, right_contribution)) - 真正的答案藏在递归过程中不断更新的全局变量(如
ans或成员变量)里 - 如果硬写成纯函数式、无状态递归(比如只靠返回值传递所有信息),逻辑会爆炸式复杂,且无法覆盖“15→20→7”这种不经过根的跨子树路径
dfs 返回值为什么是 max(0, max(left, right) + val)
这个表达式决定父节点能否从你这里“借道”。关键点在于:
- 负贡献必须截断:若
left_contribution = -5,right_contribution = -2,那从当前节点往下延伸的任何路径都只会拉低总和,此时应返回0(等价于“不选这条分支”) - 只能选一侧:返回值代表“从本节点出发、向下走一条路”的最大和,因此是
val + max(left, right),不是val + left + right - 加
max(0, ...)是安全兜底:避免把负值传上去污染父节点计算,例如节点值为-10,左右贡献都是-1,那么-10 + max(-1,-1) = -11,但实际该节点单独成路径(-10)比-11大,所以取max(0, -11) = 0,再由父节点加自己的值时自然得到-10(见下一点)
如何正确初始化全局答案并处理全负树
全负树(如 [-3,-5,-2])是最容易翻车的场景。错误做法是初始化 ans = 0 或 ans = INT_MIN 后不做校验——INT_MIN 在某些平台可能溢出,且逻辑上不直观。推荐写法:
立即学习“C++免费学习笔记(深入)”;
- 初始化
ans = root->val(至少保证根节点被纳入考虑) - 或用
ans = numeric_limits<int>::min()</int>,但必须确保第一次更新发生在叶子节点(即!node->left && !node->right时就更新ans = max(ans, node->val)) - 更稳妥的是:在
dfs入口处先更新ans = max(ans, node->val),再算左右贡献——这样哪怕左右全是负数、最终返回0,当前节点自身值也已计入答案
最易被忽略的一点:路径定义中“同一节点至多出现一次”,决定了拐点路径(左+中+右)和单侧路径(中+左 或 中+右)本质不同,而递归结构天然区分了二者。写代码时若混淆返回值语义(比如误把拐点和当返回值),整个逻辑就垮了。


















