力扣 124. 二叉树中的最大路径和 [1.0,2.0]

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:

  • 树中节点数目范围是 [1, 3 * 104]
  • -1000 <= Node.val <= 1000

题解

1.0

灵感来自通过110. 平衡二叉树,其中优化方法中,将一整棵树划分为子树,针对每个子树进行判断,通过递归合并为完整树的判断。

在此题中,编写函数针对当前节点cur,获取以cur为根节点的树的最大路径和,首先分别获取左右子树的最大路径和,然后判断此树的最大路径。(进入叶子节点子树的时候,因为为null,最大路径和就直接返回0,即空结点返回0)。
 
如何选择最大路径,当已有子树最大路径left,right时,其实有三种选择:
  • leftNode-curNode,当前节点与左子树连接的路径,那么最大路径和为left+curVal
  • curNode-rightNode,当前节点与右子树连接的路径,和为right+curVal
  • curNode,只有当前节点,和为curVal

为什么有第三种情况呢?因为有可能左右子树都是负数,加他们还不如不加。

其实这也对应着从上往下走,选路径的过程,当走到当前节点cur时,有三个方向可以走:
  • 往左子节点走
  • 往右子节点走
  • 停止,不往下走
代码如下,有详细注释
1.0
 class Solution {
public:
    int maxx=-10000;
    int work(TreeNode* cur){//以cur节点为根节点的一棵树的路径最大值
        if(cur==nullptr)
            return 0;
        int left=work(cur->left);
        int right=work(cur->right);
        int curMax=-10000;//以cur节点为根节点的一棵树的路径最大值
        curMax=max(curMax,cur->val);//与当前节点比,对应的情况是两个子树为负
        curMax=max(curMax,left+cur->val);//当前节点连接左子树的路径,注意只有一条路径,所以不能左右子树+当前节点,不然会出现F形状的路径
        curMax=max(curMax,right+cur->val);//连接右
        maxx=max(maxx,max(left+right+cur->val,curMax));//而所有树最大路径和maxx,是必须算上当前节点来比较的
        return curMax;
    }
    int maxPathSum(TreeNode* root) {
        if(root==nullptr)
            return 0;
        work(root);
        return maxx;
    }
};

2.0

如果感觉1.0的代码有太多判断,就可以参考官方中的小技巧,即获得子树最大路径和时,加一个判断,取和与0的较大值,,即可省略掉后面的判断,而且逻辑更好理解。
查看代码
 /**
 * 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 maxx=-10000;
    int work(TreeNode* cur){//以cur节点为根节点的一棵树的路径最大值
        if(cur==nullptr)
            return 0;
        int left=max(work(cur->left),0);
        int right=max(work(cur->right),0);
        
        maxx=max(maxx,left+right+cur->val);//更新maxx
        return cur->val+max(left,right);
    }
    int maxPathSum(TreeNode* root) {
        if(root==nullptr)
            return 0;
        work(root);
        return maxx;
    }
};
 
posted @ 2022-11-01 21:17  付玬熙  阅读(59)  评论(0编辑  收藏  举报