题目描述

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例1:

python递归树树干变粗 python 递归树_二叉树


示例2:

python递归树树干变粗 python 递归树_数据结构_02

解题思路

遇到二叉树的题,如果能用递归就尽量递归吧。
首先回顾递归三步骤:
1、递归终止条件及返回值
2、递推条件
3、返回值分析处理
具体到这道题,采用递归的三个步骤具体化为:
1、递归终止条件为节点为空,返回值为0
2、递推条件:分别递归左右子树,计算左右子树的节点和记为l和r
3、返回值及分析:max(0, l, r) + node.val
这个递归函数实现的是对于一个根节点,通过计算分别计算其左右子树节点和,来看其左右子树是否有正增益。

代码实现

实现部分的核心代码就是self.sum的更新了。

self.sum = max(self.sum, max(0, leftSum)+max(0,rightSum)+root.val)

在更新self.sum时有两个判断,一个是self.sum,另一个包含了两个max加上当前节点的值。
注意此处用的是

max(0, leftSum) + max(0, rightSum) + root.val

这样就是说如果左右子树对于根节点无增益的话,就用0来替代左右子树和,但同时也计算了当前节点的值。

对于这个递归函数,注意其计算顺序,先计算左子树的最大和,再计算右子树的最大和,最后返回

max(0, leftSum, rightSum) + root.val

在计算完左子树最大和后,计算右子树最大和时,代码

self.sum = max(self.sum, max(0, leftSum)+max(0,rightSum)+root.val)

此处最外层max函数的左边是左子树最大和,右边是右子树最大和,self.sun更新后即为左右子树中和较大的那一个。
最后一次更新self.sum时,最外层max函数左边为左右子树最大和中较大的那一个,右边为左子树增益(若左子树和小于0则无增益,用0替代)加上右子树增益加上根节点的和。

class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        self.sum = float('-inf')
        def dfs(root):
            if not root:
                return 0
            leftSum = dfs(root.left)
            rightSum = dfs(root.right)
            self.sum = max(self.sum, max(0, leftSum)+max(0,rightSum)+root.val)
            return max(0, leftSum, rightSum) + root.val
        dfs(root)
        return self.sum