python-leetcode 49.二叉树中的最大路径和
题目:
二叉树中的路径被定义为一条节点序列,序列中每对相邻节点之间都存在一条边,同一个节点在一条路径序列中至多出现一次,该路径至少包含一个节点,且不一定经过根节点。
路径和是路径中各节点值得总和,给定二叉树得根节点root,返回其最大路径和
方法一:递归
首先,考虑实现一个简化的函数 maxGain(node),该函数计算二叉树中的一个节点的最大贡献值,具体而言,就是在以该节点为根节点的子树中寻找以该节点为起点的一条路径,使得该路径上的节点值之和最大。
-
空节点的最大贡献值等于 0
-
非空节点的最大贡献值等于节点值与其子节点中的最大贡献值之和(对于叶节点而言,最大贡献值等于节点值)
叶节点 9、15、7 的最大贡献值分别为 9、15、7。得到叶节点的最大贡献值之后,再计算非叶节点的最大贡献值。节点 20 的最大贡献值等于 20+max(15,7)=35,点 −10 的最大贡献值等于 −10+max(9,35)=25,
上述计算过程是递归的过程,因此,对根节点调用函数 maxGain
,即可得到每个节点的最大贡献值。
根据函数 maxGain
得到每个节点的最大贡献值之后,如何得到二叉树的最大路径和?对于二叉树中的一个节点,该节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值,如果子节点的最大贡献值为正,则计入该节点的最大路径和,否则不计入该节点的最大路径和。维护一个全局变量 maxSum
存储最大路径和,在递归过程中更新 maxSum
的值,最后得到的 maxSum
的值即为二叉树中的最大路径和。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def __init__(self):
self.maxSum=-1e9
def maxPathSum(self, root):
"""
:type root: Optional[TreeNode]
:rtype: int
"""
def maxGain(node):
if not node:
return 0
#递归计算左右子节点的最大贡献值,只有在最大贡献值大于 0 时,才会选取对应子节点
leftGain=max(maxGain(node.left),0)
rightGain=max(maxGain(node.right),0)
#节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
priceNewpth=node.val+leftGain+rightGain
#更新答案
self.maxSum=max(self.maxSum,priceNewpth)
#返回节点最大贡献值
return node.val+max(leftGain,rightGain)
maxGain(root)
return self.maxSum
时间复杂度:O(N)N 是二叉树中的节点个数。对每个节点访问不超过 2 次。
空间复杂度:O(N)主要取决于递归调用层数,最大层数等于二叉树的高度,最坏情况下,二叉树的高度等于二叉树中的节点个数
源自力扣官方题解