LeetCode 124. 二叉樹中的最大路徑和 | Python

fondtiger發表於2021-09-09

124. 二叉樹中的最大路徑和


題目來源:力扣(LeetCode)

題目


給定一個非空二叉樹,返回其最大路徑和。

本題中,路徑被定義為一條從樹中任意節點出發,達到任意節點的序列。該路徑至少包含一個節點,且不一定經過根節點。

示例 1:

輸入: [1,2,3]

       1
      / 
     2   3

輸出: 6

示例 2:

輸入: [-10,9,20,null,null,15,7]

   -10
   / 
  9  20
    /  
   15   7

輸出: 42

解題思路


思路:遞迴

題目中所給出的路徑概念是指【一條從樹中任意節點出發,達到任意節點的序列。該路徑至少包含一個節點,且不一定經過根節點】。

也就是說,要求出路徑和,得計算節點能提供的最大貢獻值。

對於節點能提供的貢獻值,分為如下部分:

  • 空節點提供的貢獻值為 0;
  • 對於非空節點提供的貢獻值,等於當前節點的值與其子節點中提供最大貢獻值的和。

現在以示例 1 來分析說明下:

輸入: [1,2,3]

       1
      / 
     2   3

在這裡葉子節點 2,3,能提供的貢獻值就是 2, 3。

而葉子節點 1,能夠提供的貢獻值為 1+21+3

那我們假設:如果節點 1 前面還有父節點,那麼這裡可能的路徑就會變成:

  • 2 + 1 + 3
  • 2 + 1 + 1 的父節點
  • 3 + 1 + 1 的父節點

其中第一種情況,就是求節點的最大路徑和。這裡節點的最大路徑和取決於該節點與其左右子節點的最大貢獻值之和。當然,在這裡,如果子節點的貢獻值為負,則選擇不納入。因為負數的貢獻值新增進來反而會讓結果變小。

對於第二種和第三種情況來說,這裡就是遞迴求得左右子節點的貢獻值,從中取更優的方案。

這裡最主要的就是維護一個儲存最大路徑和的變數 max_path_sum,遞迴的過程中維護更新這個值,從而求得最大值。

具體的程式碼實現如下。

程式碼實現


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def __init__(self):
        # 儲存最大路徑和
        self.max_path_sum = float('-inf')

    def maxPathSum(self, root: TreeNode) -> int:
        def max_contr(node):
            # 遞迴求節點最大貢獻值
            # 同時維護經過節點的最大路徑和
            # 空節點的貢獻值為 0
            if not node:
                return 0

            # 遞迴計算左子節點的貢獻值,
            left = max(0, max_contr(node.left))
            # 遞迴計算右子節點的貢獻值
            right = max(0, max_contr(node.right))

            # 經過當前節點的最大路徑和
            self.max_path_sum = max(self.max_path_sum, left + node.val + right)

            # 當前節點的貢獻值,取左右子節點中的更優方案
            node_contr = node.val + max(0, max(left, right))
            # 這裡返回的貢獻值是給當前節點的上游節點
            return node_contr

        max_contr(root)
        return self.max_path_sum

實現結果


圖片描述

總結


  • 從題目中得到的資訊可以知道,要求最大路徑和,需要求得節點能夠提供的貢獻值。
  • 對於節點而言,提供的貢獻值分為兩部分:
    • 空節點的貢獻值為 0;
    • 對於非空節點而言,當前節點能提供的貢獻值為當前節點的值與其子節點中能提供的最大貢獻值之和
  • 對於非空節點而言,我們需要遞迴的方法求得每個節點的貢獻值。同時,需要維護最大路徑和,在這裡,該節點的路徑和取決於當前節點的值與其左右子節點的最大貢獻值。
  • 這裡需要注意:當貢獻值為負時,不計入節點的最大路徑和。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2508/viewspace-2825699/,如需轉載,請註明出處,否則將追究法律責任。

相關文章