二叉树的最大路径和问题
字数 939 2025-11-11 00:26:13
二叉树的最大路径和问题
题目描述
给定一个非空二叉树,每个节点有一个整数值,找到一条路径(从树中任意节点出发,到达任意节点,方向只能从上往下),使得路径上的节点值之和最大。返回这个最大值。路径至少包含一个节点,且不一定经过根节点。
解题思路分析
这个问题看似复杂,但可以通过分解为子问题来解决。关键点在于:
- 路径可以是任意节点到任意节点的路径,不一定经过根节点
- 路径方向必须是单向的(父节点→子节点)
- 我们需要考虑三种情况:左子树路径、右子树路径、跨越根节点的路径
循序渐进讲解
步骤1:理解路径的三种可能情况
对于任意节点,经过该节点的最大路径和有三种可能:
- 情况1:只包含当前节点本身
- 情况2:当前节点 + 左子树的某条路径
- 情况3:当前节点 + 右子树的某条路径
- 情况4:当前节点 + 左子树路径 + 右子树路径(这种路径不能继续向上延伸)
步骤2:定义递归函数
我们定义一个递归函数 maxPathSumHelper(node),它返回两个值:
- 以该节点为起点的向下最大路径和(可用于父节点计算)
- 经过该节点的最大路径和(可能是跨越左右子树的路径)
步骤3:递归处理子问题
对于每个节点:
- 如果节点为空,返回0(空节点不贡献值)
- 递归计算左子树和右子树的最大路径和
- 注意:如果子树的最大路径和为负数,我们宁愿不选择它(取0)
步骤4:计算当前节点的各种路径和
- 以当前节点为起点的最大路径和 = max(0, 左子树最大路径和, 右子树最大路径和) + 节点值
- 经过当前节点的最大路径和 = max(以当前节点为起点的最大路径和, 节点值 + 左子树最大路径和 + 右子树最大路径和)
步骤5:维护全局最大值
在递归过程中,我们需要维护一个全局变量来记录整个树中的最大路径和。
具体实现
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
self.max_sum = float('-inf')
def dfs(node):
if not node:
return 0
# 递归计算左右子树的最大贡献值
left_max = max(dfs(node.left), 0)
right_max = max(dfs(node.right), 0)
# 计算经过当前节点的最大路径和
current_max = node.val + left_max + right_max
self.max_sum = max(self.max_sum, current_max)
# 返回以当前节点为起点的最大路径和
return node.val + max(left_max, right_max)
dfs(root)
return self.max_sum
步骤6:复杂度分析
- 时间复杂度:O(n),每个节点只访问一次
- 空间复杂度:O(h),其中h是树的高度,主要是递归栈空间
关键要点总结
- 使用后序遍历(左右根)来保证先处理子问题
- 负贡献值要舍弃(取0)
- 区分"以节点为起点的路径"和"经过节点的路径"
- 使用全局变量记录最大值
这个问题的核心思想是将复杂问题分解为子问题,通过递归自底向上地解决,是二叉树问题中的经典范例。