1. 程式人生 > >每天一道LeetCode-----計算二叉樹的最大路徑和,路徑只需要從一個節點到達另一個節點,無其他要求

每天一道LeetCode-----計算二叉樹的最大路徑和,路徑只需要從一個節點到達另一個節點,無其他要求

Binary Tree Maximum Path Sum

給定一個二叉樹,計算二叉樹中最長的路徑和,路徑只需要從一個節點到另一個節點,不需要經過根節點,也不需要從葉子節點開始,但至少包含一個節點

乍一看,二叉樹上任意一條路徑都有可能是最後的結果,而解決二叉樹又必須使用遞迴,如果在遞迴的過程中計算以當前節點為根節點的子樹的最長路徑和,同時要求必須經過當前節點,那麼在遞迴的過程中就可以將所有可能都遍歷到

但是在遞歸向上返回時不能返回上述過程計算的路徑和,因為返回的過程意為著路徑還需要向上延伸,那麼到達當前節點向上延伸,就不可能將左右兩邊都計算到。所以在向上返回時需要返回一條經過當前節點但是隻在一側的路徑長

程式碼如下

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxPathSum(TreeNode* root) {
        int maxSum = INT_MIN;
        maxPathSum(root, maxSum);
        return
maxSum; } private: /* 函式計算必須經過root的路徑長,更新maxSum * 返回必須經過root,但是隻包含一側的路徑長 */ int maxPathSum(TreeNode* root, int& maxSum) { if(!root) return 0; /* 計算左右子樹的路徑長 */ int leftSum = maxPathSum(root->left, maxSum); int rightSum = maxPathSum(root->right, maxSum); /* 必須經過root */
int sum = root->val; /* 大於0才需要加 */ sum += (leftSum > 0) ? leftSum : 0; sum += (rightSum > 0) ? rightSum : 0; /* 更新maxSum,maxSum中儲存遍歷到的路徑和的最大值 */ maxSum = std::max(maxSum, sum); /* 只能返回一側,當然減去小的那邊 */ if(leftSum > 0 && rightSum > 0) return sum - std::min(leftSum, rightSum); else return sum; } };

本題還是利用遞迴,不過解決思路不太容易理解,需要弄清楚如何遍歷所有的路徑,因為路徑必須有節點,所以可以計算必須經過根節點的路徑和求最大值,需要注意的是遞歸向上返回時不可以直接返回路徑和,因為向上返回意為著路徑向上延伸,那必須最多隻能經過當前節點的左右子樹中的一個,所以需要減去較小的子樹