已知某个国家中的城市呈二叉树形状分布。这时国家突然出现了断电危机。现在政府要求电力修理部队可以从任意一个城市出发来修理各个城市的电力设施。每个城市有不同的紧急程度,所以以不同的路径来修理电力设施会得到不同的收益。二叉树节点上的数字代表修理电力设施的收益(可以为负)。不幸的是,修理部队因为种种原因不能掉头,这就意味着其不能来到同一个城市两次,城市与城市之间的边也只能走一回。在这种情况下,我们需求解出一条路径,使修理的收益最大,路径上的和最大。
如图所示,最优的修理线路应该是蓝色的路径,总共的收益为7。
如果如图所示,那最大的收益为11。
如果如图所示,最大为20.
对于这个问题而言,树上的每一个节点(城市)都只有两个可能:停或者不停。
“停”值:以当前节点为根节点的子树中,所有已经结束的路径中所能得到收益的最大值。
“不停”值:以当前节点为根节点的子树中,仍可被延伸的所有路径中所能得到收益的最大值。
(1)节点k的停值=max(其左子节点的不停值,其右子节点的不停值,其左子节点的停值,其右子节点的停值,其左子节点的不停值加上其右子节点的不停值再加上k自身的收益值)。
五种情况的前两种左子节点的停值、右子节点的停值分别为左子树和右子树中停止路径的最大值,有可能成为全图路径的最大值。而中间两种情况左子节点的不停值、右子节点的不停值记录的分别为左子树和右子树的可延伸路径的最大值。虽然这些路径还可继续,但也可以随时终止,即时止损(因为收益值可以为负)。最后一种情况则是将左子树和右子树的可延伸路径串联起来,如果所有节点的收益值为正,则其必为全图路径的最大值。
(2)节点k的不停值=max(节点k自身的收益值,k自身的收益值再加上其左子节点的不停值,k自身的收益值再加上其右子节点的不停值)。
如果要求路径不能停止,要不从左子树或右子树中挑一个子树中不停的路径连接上现节点k,要不就不连接子树保留的路径而从节点k重新开启新的路径
class TreeNode: # 二叉树节点定义
def __init__(self, x):
self.val = x # 节点值
self.left = None # 左子节点
self.right = None # 右子节点
# 城市危机最终代码
class Solution:
def maxPathSum(self, root): # 输出最大路径和的方法
return max(self.helper(root)) # 调用helper方法,传入根节点,输出返回的两个值中的最大值
def helper(self, root): # helper方法,输出一个二维数组 [不停值,停值]
if root == None: # 如果节点为空,输出两个最小值
return float('0'), float('0')
leftY, leftN = self.helper(root.left) # 得到左子节点的不停值与停值
rightY, rightN = self.helper(root.right) # 得到右子节点的不停值与停值
# 节点k停值=max(其左子节点不停值,其右子节点不停值,其左子节点停值,其右子节点停值,其左子节点不停值加上其右子节点不停值加上k自身收益值)
no = max(leftN, rightN, leftY, rightY, root.val + leftY + rightY) # 停值
# 节点k不停值=max(k自身收益值,k自身收益值再加上其左子节点不停值,k自身收益值再加上其右子节点不停值)
yes = max(root.val + leftY, root.val + rightY, root.val) # 不停值
return yes, no # 输出 [不停值,停值]
输入
二叉树为
输出