# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxPathSum(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def max_gain(node):
nonlocal max_sum
#nonlocal的作用是,当函数内嵌套函数时,用nonlocal声明 max_sum 是局部变量,会根据上一次函数的更新而更新
if not node:
return 0
# max sum on the left and right sub-trees of node
left_gain = max(max_gain(node.left), 0)
right_gain = max(max_gain(node.right), 0)
# the price to start a new path where `node` is a highest node
price_newpath = node.val + left_gain + right_gain
# update max_sum if it's better to start a new path
max_sum = max(max_sum, price_newpath)
# for recursion :
# return the max gain if continue the same path
return node.val + max(left_gain, right_gain)
max_sum = float('-inf')
max_gain(root)
return max_sum
max_sum是我们要的答案,我们先初始化为一个最小的float,方便我们替换,因为我们找的是最大的路径,用最小的float来初始化,无论碰到什么数我们都会更新它。
我们来讲一下怎么递归
首先max_gain(node)这个函数的作用是以node为根节点,也就是树的最上端那个点形成的这棵二叉树,它是取来自左侧子树从下往上的最大路径还是取来自右侧子树从下往上的最大路径,加这个node点本身,可以获得的最大路径值,并返回这个最大路径值。
解释一下这里的从下往上,就是这条路径只有从子叶节点到父叶节点再到现在这个根节点node这种,不包含可以回头的那种,就是子叶节点到父叶节点又回去子叶节点的那种情况。
举例说明就是
以-10这个node为例
max_gain(-10为根节点的这棵树)是得到来自左侧子树从下往上的最大路径(9)和来自右侧子树从下往上的最大路径(15+20),不包含(15+20+7)这种回头的情况。(15+20+7)这种情况我们在递归中会介绍怎么处理。
根据我们之前给出的数学归纳法解法
我们要给出n = 0 的时候的解,对应碰到最后一层叶子节点,再调用函数就到None了,所以return 0
if not node:
return 0
n = k 时 如何推到 n = k + 1 呢
left_gain = max(max_gain(node.left), 0)
right_gain = max(max_gain(node.right), 0)
price_newpath = node.val + left_gain + right_gain
从这个node开始,我们能从左侧子树得到什么呢?
如果来自左侧子树的从下往上的最大路径比0还要小,右侧子树可以带来正数的路径和,还完全没有必要选左边边的子树了,因为加起来必定比node本身要小,我们之选右边
同理我们可以处理来自右侧子树的从下网上的最大路径
还有可能我只选这个node,左右两边都是负收益
那一开始(15+20+7)那种情况怎么处理呢?这种就对应着left_gain和right_gain都是有利可图的,也就是我放弃继续往上走了,我回去找左侧到节点node到右侧的这种路径
对于递归到最底下的叶子结点,price_newpath就是叶子结点本身的值
上面的各种情况都能用这句话来计算最大路径和,肥肠牛逼!
我们用一个新路径的价格的变量来记录它,如果它比历史的最大路径和大,那么就改变max_sum的值为这个值
max_sum = max(max_sum, price_newpath)
但是我们的函数最后还是要返回n = k + 1时候的max_gain()
等于node加上来是选左侧子树还是右侧子树从下往上的最大路径和
return node.val + max(left_gain, right_gain)
实际上递归完成,同时也更新完了最大路径和。