思路
這道題的解法很巧妙,我要着重介紹這道題。
明確幾個概念
- 路徑:這裏的路徑指的是,從樹中的某個節點到另一個節點,包括終點和起點,僅有一個點也算是一條路徑。
- 路徑和:這裏的路徑和指的是,路徑中所有節點值的和。
- 最大路徑和:顧名思義,就是所有路徑中最大的那條路徑。
明確經過一個節點的路徑的三種情況
這裏我參考了官方題解裏的說明。經過一個點的路徑有三種情況(當然這裏指的是一般情況)。
- left----root----parent(拐向父節點);
- right----root----parent(拐向父節點);
- left—root—right;
做法
遞歸每個節點,維護一個全局變量maxsum,遞歸過程中維護這個全局變量。然後我發現了三個有意思的地方。
- 遞歸的每層的含義:dfs(root) 計算了經過root節點的最長路徑和(不包括向上走的路徑),並將其更新到maxsum中。
- 遞歸的返回值:返回root節點向上走時所能提供最大貢獻,即left->root與right->root中較大者。
- 對負值的處理:由於遞歸left或right節點的返回值可能爲負,若直接進行計算值會變小,就取
left=max(0,dfs(left))
和right=max(0,dfs(right))
,相當於捨棄左樹或右數,只取節點本身。注意,因爲我們的遞歸裏計算的是經過root的路徑,所以根節點值爲負數時也要參與運算。
代碼
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private int maxsum = -(1<<31);
public int max(int a,int b){return a>b?a:b;}
private int dfs(TreeNode root){
if(root==null)return 0;
int left=max(0,dfs(root.left));
int right=max(0,dfs(root.right));
//更新全局變量
this.maxsum=max(this.maxsum,left+root.val+right);
//返回向上的最大路徑長度
return max(left,right)+root.val;
}
public int maxPathSum(TreeNode root) {
this.maxsum = -(1<<31);
dfs(root);
return this.maxsum;
}
}