最大路径和需分离单支路贡献与跨子树路径:单支路值(max(0, 左/右) + 当前值)用于向上递归,必须≥0;跨子树路径(左+当前+右)仅更新全局最大值,不返回。

最大路径和不是“从根到叶子”的单向路径,而是任意起点到任意终点、沿父子边连通的路径;直接套用普通 DFS 会漏掉跨左右子树的路径,必须用两个逻辑分离:一个返回单支路最大贡献值,一个维护全局最大路径和。
为什么不能只写一个 return 值的递归函数
常见错误是让 maxPathSum 直接返回“以当前节点为最高点的最大路径和”,但这样无法向上提供有效子结构信息——父节点需要知道左/右子树能“向上延伸”的最大单支路和(即最多贡献多少),而不是整条跨子树的路径。否则父节点无法拼出自己的跨子树路径(左支 + 当前节点 + 右支)。
- 单支路和用于向上递归,必须 ≥ 0(负贡献不如不走,可截断)
- 跨子树路径(
left + root->val + right)只参与全局更新,不返回给父节点 - 若强行统一返回类型,会导致状态混淆,比如把跨子树值错当单支路传上去,引发错误累加
onePath 函数的设计要点与参数陷阱
onePath 是核心辅助函数,它返回的是“从当前节点出发、向下延伸的单方向最大路径和”(含当前节点),用于被父节点调用拼接。它的实现有三个关键约束:
- 空节点必须返回
0,否则max(0, l)截断逻辑失效 - 返回值是
max(0, max(l, r)) + root->val,不是max(l, r) + root->val——负子树必须舍弃 - 全局变量(如
int& ret)必须在进入左右子树递归后、返回前更新,顺序错会导致漏更新 - 不要在
onePath内做if (!root) return INT_MIN,这会让 0 截断失效,且空节点不应贡献负值
如何避免更新全局最大值时的边界错误
全局最大值更新语句:ret = max(ret, max(0, l) + max(0, r) + root->val),这里容易出错的点很具体:
立即学习“C++免费学习笔记(深入)”;
-
l和r是子树单支路返回值,可能为负,但路径允许只取当前节点(即max(0,l)和max(0,r)都为 0 时,结果就是root->val) - 不能写成
max(l, 0) + max(r, 0) + root->val——语法等价,但可读性差,且易误写为max(l + r, 0) + ... - 初始
ret必须设为INT_MIN,不能是0;树中全是负数时,最大路径和就是最大的那个负数(如[-3]应返回-3) - 更新操作不能放在递归入口处,必须在获取
l、r之后,否则子树结果未计算就更新,值为未定义
回溯在这里其实不适用
有人看到“路径”“递归”就下意识想用回溯(push/pop 路径数组),但本题求的是数值和,不是枚举路径本身。所有状态都通过函数返回值和引用参数传递,没有中间容器需要维护或还原。强行加 vector 回溯不仅性能下降(拷贝开销),还会模糊递归意图——这不是路径收集问题,是树形 DP 的状态转移问题。
真正容易被忽略的是:跨子树路径只在此节点计算一次,且绝不向上返回;而单支路值每次必返回。这个“一用一返”的分工一旦混淆,整个逻辑就崩了。


















