[二叉树] 二叉树中的最大路径和---leetcode124
1. 題目描述
路徑 被定義為一條從樹中任意節點出發,沿父節點-子節點連接,達到任意節點的序列。同一個節點在一條路徑序列中 至多出現一次 。該路徑 至少包含一個 節點,且不一定經過根節點。
路徑和 是路徑中各節點值的總和。
給你一個二叉樹的根節點 root ,返回其 最大路徑和 。
2. 思路
對于任意一個節點, 如果最大和路徑包含該節點, 那么只可能是兩種情況:
? ? 1. 其左右子樹中所構成的和路徑值較大的那個(如果左子樹或右子樹構成的最大路徑和為負數,則置為零,表示最大路徑不經過這個子樹)加上該節點的值后向父節點回溯構成最大路徑,也可能沒有左右子樹,只有該節點的值往前回溯。
? ? 2. 左右子樹都在最大路徑中, 加上該節點的值構成了最終的最大路徑。即,該節點是最大路徑的根節點。
?
遞歸時,將每個結點作為一個根結點傳入遞歸函數。對于當前的這個結點,以它為根結點,計算它左子樹路徑的最大和,右子樹路徑的最大和。通過這個結點,當前是看做是以它根結點,這個結點的最大路徑和就是:左子樹最大路徑和(大于0的話)+右子樹最大路徑和(大于0的話)+根結點的值。然后更新當前計算的MAX是多少,也就是我們的結果。
遞歸函數的返回值是:當前這個結點的左子樹最大路徑和,或者是右子樹最大路徑和。再加上結點值。因為,這樣得到的一條最大路徑,就可以作為這個結點的父節點的一條路徑,用于父節點的計算。
?
我們首先考慮什么樣的路徑可以是最大路徑,根據題意,只要是一個結點到另一結點即可。那么我們可以分成兩種:
-
單向路徑,即路徑中所有的結點都不在同一層,比如示例2中的-10→20→7。
- 雙向路徑,路徑中,以根節點為最高層,左右兩個單路徑向兩邊延伸,比如示例二中的答案15←20→7。
我們考慮以每一個結點為根,可以構成的最大單向路徑和maxgain為多少,葉節點的maxgain就為它本身的值,其他結點的maxgain則為它自己的值與它左右結點中較大的maxgain之和。
如示例2中,首先15和7的maxgain為本身,然后20的maxgain為20+max(15,7)=35,然后9的maxgain為本身,-10的maxgain為-10+max(9,35)=25。
?
我們再考慮答案與maxgain的關系,如果以某個點node為路徑的根。
- 雙向路徑的和為? ? node.val+maxgain(node.left)+maxgain(node,right)
- 單向路徑為? node.val+maxgain(node.left) 或 node.val+maxgain(node.right)
我們要找到這個結點為根的最大路徑和,那么就是上面三個式子的最大值,而只有在左結點或右結點的maxgain<0,答案才會是下面的式子,所以我們首先判斷左右結點的maxgain是不是小于0,如果小于0,置為0,這樣就都可以使用上面的式子來表示了。
由于計算路徑和的時候,所需的值都是這個節點以及下一層的值,所以在遍歷計算maxgain的同一個遞歸即可完成,只要使用一個全局變量更新結果即可。
?
注意:最長的路徑肯定是屬于“從一端的最左側到這端的最右側” 這個完整鏈條的一部分。
3 Python 代碼
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = Noneclass Solution:def __init__(self): # 定義一個result屬性self.result = float("-inf")def maxPathSum(self, root: TreeNode) -> int:if root == None:return 0self.getMax(root)return self.resultdef getMax(self,root): # 定義一個輔助函數if root == None: # 如果當前節點為空就表示包含當前節點的最大路徑為0return 0# 遞歸的計算當前節點的左子樹和右子樹能提供的最大路徑和,如果為負,就置為零(相當于從頭開始)left = max(0,self.getMax(root.left)) right = max(0,self.getMax(root.right))# 注意:最長的路徑肯定是屬于從一端的最左側到這端的最右側的一部分# 每計算一次左右子樹的最大值,就更新當前的resultself.result = max(self.result,left + right + root.val)# 往父節點回溯的話,最大路徑就不能同時包含左右兩個子樹,# 因此需要用左右子樹較大的那個子樹加上當前節點的值進行回溯return max(left,right) + root.val #(遞歸函數,返回的是回溯需要的式子,而不是返回最終結果(比如這里的 return result))回溯往往可以用遞歸來進行實現,當運用遞歸函數的時候,return的不是函數實現的結果
而是回溯到上層所需要的式子(大部分最終結果和回溯返回所需要的式子是相同的),可能不是這個函數所要實現的最終功能。回溯所需要的式子,以這個題目為例,在定義getMax函數的時候,我們返回的是max(left,right)+ root.val,因為從當前節點回溯到上層父節點的話,需要給上層節點提供由當前節點和某一子樹所構成的最大路徑和。而最終的結果result是在遞歸的過程中不斷地更新沒有作為函數的return。
?
?
?
總結
以上是生活随笔為你收集整理的[二叉树] 二叉树中的最大路径和---leetcode124的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 银行卡怎么销户和注销
- 下一篇: [二叉树]二叉树中和为某一值的路径 (剑