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

題目描述(困難難度)

考慮一條路徑,可以從任意節點開始,每個節點最多經過一次,問經過的節點的和最大是多少。

解法一 遞歸

參考了 這裏

首先看到二叉樹的題,肯定就是想遞歸了。遞歸常規的思路,肯定是遞歸考慮左子樹的最大值,遞歸考慮右子樹的最大值。

public int maxPathSum(TreeNode root) {
    if (root == null) {
        return Integer.MIN_VALUE;
    }
    //左子樹的最大值
    int left = maxPathSum(root.left);
    //右子樹的最大值
    int right = maxPathSum(root.right);  
    //再考慮包含根節點的最大值
    int  all = ....;
    return Math.max(Math.max(left, right), all);
}

問題就來了,怎麼考慮包含根節點的最大路徑等於多少?因爲我們遞歸求出來的最大 left 可能不包含根節點的左孩子,例如下邊的情況。

     8
    / \
  -3   7
 /  \
1    4

左子樹的最大值 left 肯定就是 4 了,然而此時的根節點 8 並不能直接和 4 去相連。所以考慮包含根節點的路徑的最大值時,並不能單純的用 root.val + left + right

所以如果考慮包含當前根節點的 8 的最大路徑,首先必須包含左右孩子,其次每次遇到一個分叉,就要選擇能產生更大的值的路徑。例如下邊的例子:

      8
    /  \
   -3   7
 /    \
1      4
 \    / \    
  3  2   6

考慮左子樹 -3 的路徑的時候,我們有左子樹 1 和右子樹 4 的選擇,但我們不能同時選擇
如果同時選了,路徑就是 ... -> 1 -> -3 -> 4 -> ... 就無法通過根節點 8 了
所以我們只能去求左子樹能返回的最大值,右子樹能返回的最大值,選一個較大的

假設我們只考慮通過根節點 8 的最大路徑是多少,那麼代碼就可以寫出來了。


public int maxPathSum(TreeNode root) {
    //如果最大值是負數,我們選擇不選
    int left = Math.max(helper(root.left), 0);
    int right = Math.max(helper(root.right), 0); 
    return root.val + left + right;
}

int helper(TreeNode root) {
    if (root == null) return 0; 
    int left = Math.max(helper(root.left), 0);
    int right = Math.max(helper(root.right), 0);  
    //選擇左子樹和右子樹產生的值較大的一個
    return root.val + Math.max(left, right);
}

接下來我覺得就是這道題最精彩的地方了,現在我們只考慮了包含最初根節點 8 的路徑。那如果不包含當前根節點,而是其他的路徑呢?

可以發現在 helper 函數中,我們每次都求了當前給定的節點的左子樹和右子樹的最大值,和我們 maxPathSum 函數的邏輯是一樣的。所以我們利用一個全局變量,在考慮 helper 函數中當前 root 的時候,同時去判斷一下包含當前 root 的路徑的最大值。

這樣在遞歸過程中就考慮了所有包含當前節點的情況。

int max = Integer.MIN_VALUE;

public int maxPathSum(TreeNode root) {
    helper(root);
    return max;
} 
int helper(TreeNode root) {
    if (root == null) return 0;

    int left = Math.max(helper(root.left), 0);
    int right = Math.max(helper(root.right), 0);
    
    //求的過程中考慮包含當前根節點的最大路徑
    max = Math.max(max, root.val + left + right);
    
    //只返回包含當前根節點和左子樹或者右子樹的路徑
    return root.val + Math.max(left, right);
}

這道題最妙的地方就是在遞歸中利用全局變量,來更新最大路徑的值,太強了。前邊遇到過和全局變量結合的遞歸,例如 106 題,當遞歸和全局變量結合有時候確實會難理解些。而在 110 題 中也應用了和這個題一樣的思想,就是發現遞歸過程和主函數有一樣的邏輯,此時可以在遞歸過程中就可以進行求解。

更多詳細通俗題解詳見 leetcode.wang

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章