算法图解——求二叉树中的最大路径和

题目来源

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。

该路径至少包含一个节点,且不一定经过根节点。

示例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....

原文地址:https://www.cnblogs.com/gjmhome/p/14157616.html