算法圖解——求二叉樹中的最大路徑和


題目來源

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

本題中,路徑被定義為一條從樹中任意節點出發,沿父節點-子節點連接,達到任意節點的序列。

該路徑至少包含一個節點,且不一定經過根節點。

示例1:

輸入:[1,2,3]

       1
      / \
     2   3

輸出:6

示例2:

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

    -10
    / \
   9  20
      /  \
     15   7

輸出:42 
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。

 題目分析

有沒有發現這一篇多了這一小節,捂臉......因為我怕你們看不懂題(我沒看懂題)。

理解該題目,關鍵是理解其中的“最大路徑”,到底這個路徑是怎么定義的?

有人說,題目上不是說了嗎?是呀,但是意思你真的看懂了嗎?

其實我舉個小栗子你就知道了。

有二叉樹abc,a 是根結點(遞歸中的 root,當然,也可以加上e是a的父節點),bc 是左右子結點(代表其遞歸后的最優解)。
最大的路徑,可能的路徑情況:

      e    
     /
    a
   / \
  b   c

那么,最大路徑只可能有三種情況:

  1. b + a + c。
  2. b + a + e(a 的父結點)。
  3. a + c + e (a 的父結點)。

為什么是這樣呢?下面做一些說明:

其中情況 1,表示如果不聯絡父結點的情況,或本身是根結點的情況,即沒有父節點。這種情況是沒法遞歸的,但是結果有可能是全局最大路徑和。

情況 2 和 3,遞歸時計算 a+b 和 a+c,選擇一個更優的方案然后加上e(如果a有父節點的話)返回。

這樣其實就得先比較左右子樹的最大路徑和,然后再和當前全局最大路徑和比較,大的話,可以再往上遞歸。那么,這里為什么要和全局最大路徑和做比較呢?對嘍,因為結點有可能是負值,最大和肯定就要想辦法舍棄負值(max(0, x))max(0,x))。

 

但是上面 3 種情況,無論哪種,a 作為聯絡點,都不能夠舍棄。

 

題目解答

C++:/** * Definition for a binary tree node. * struct TreeNode {

 * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: int maxSum = INT_MIN;
  //比較兩者取較大值
int max(int a,int b){ return a>b?a:b; }   //自己的遞歸函數 int mymax(TreeNode * root){
    //遇到葉子節點就返回0;
if(root==NULL){ return 0; }
     //左右子節點分別遞歸;之所以和0比較就是,如果子樹的最大徑和是負數,那么就舍棄掉,你是負的要你何用?大家說是不是?
int leftSum = max(0,mymax(root->left)); int rightSum = max(0,mymax(root->right));
     //計算當前最大路徑和為左路徑和+右路徑和+該節點值,因為不確定該節點是否有父節點。所以先計算出來存起來備用。
int curSum = leftSum+rightSum+root->val;
    //比較當前最大路徑和 和 歷史最大路徑和;如果當前最大路徑和較大,那么將全局歷史最大路徑和更新,否則不變,但是不管哪種,
    //返回的值都要加上root的值
maxSum
= max(maxSum, curSum); return max(leftSum,rightSum)+root->val; } int maxPathSum(TreeNode* root) { mymax(root); return maxSum; } };

 

 

可以舉例分析:

    a
   / \
  b   c

當為:

    2
   / \
  1   3
//最大值為6
    2
   / \
  1   -1
//最大值為3
    -2
   / \
  1   3
//最大值為3

通過以上例子,就能知道最后兩步 maxSum = max(maxSum, curSum);       return max(leftSum,rightSum)+root->val; 的意義了。

 

over....

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM