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