124.二叉树的最大路径和

/**
 *
 * 124.二叉树中的最大路径
 * 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
 * 路径和 是路径中各节点值的总和。
 * 给你一个二叉树的根节点 root ,返回其 最大路径和 。
 *
 * 提示:
 * 树中节点数目范围是 [1, 3 * 104]
 * -1000 <= Node.val <= 1000
 *
 * @since 2024/6/8
 */
public class Solution {

    //全局结果
    int GLOBAL_MAX_VALUE = Integer.MIN_VALUE;

    /**
     * 问题分析:
     * 路径和并不要求从根节点出发和到叶子节点结束,可以是二叉树中任意联通的几个节点。
     * 画图分析,可以将问题拆解计算每个子树的最大值。
     * 理解:最大值是如何产生的?最大值总是来源于左右子树或者当前根节点本身。对于某个根节点的最大值,有以下几种可能:
     * 1.其左子树的最大值+当前根节点
     * 2.其右子树的最大值+当前根节点
     * 3.仅仅是当前根节点
     * 4.跨根节点的最大路径
     *
     * 只需要求出每个节点的最大路径分支(前面3种情况),得到之后顺便计算情况4,用来获取可能的最大值即可。
     * 即对于每个节点,在递归计算的时候是需要计算单独分支的最大值即可,不需要计算跨节点的最大值,跨节点的最大值可以临时计算一下,用于判断是否可以获取到更大的值即可。
     *
     * 情况4只是用来比较是否可以获取到更大的值,可以通过单向,不跨节点的分支路径计算得到,因此设计的递归方法只需要计算该节点下,单向路径的最大和
     *
     * 来自左子树中较大的分支,以及右子树中较大的分支,分别与0比较,大于0的情况下才加上
     *
     */
    public int maxPathSum(TreeNode root) {
        if (root == null) {
            return 0;
        }

        //调用方法递归遍历左右根节点,并记录全局最大值
        calculateMaxValue(root);

        return GLOBAL_MAX_VALUE;
    }


    /**
     * 递归方法:计算以root为根节点的最大路径和
     * 注意:不包含跨根节点的情况,因此跨节点的路径和可以通过单向的路径和简单计算得到,只是用来比较下是否可以获取全局最大值,在每个节点计算单向最大值之后顺便计算即可。
     *
     * 1.其左子树的最大值+当前根节点
     * 2.其右子树的最大值+当前根节点
     * 3.仅仅是当前根节点
     *
     * 全局最大值可能来自于上面3种情况,或者来自于 左子树最大值+右子树最大值+根节点
     */
    private int calculateMaxValue(TreeNode root) {
        if (root == null) {
            return 0;
        }

        //分别计算左右子树的最大路径(单向)和
        int leftMax = calculateMaxValue(root.left);
        int rightMax = calculateMaxValue(root.right);

        //比较获取root节点的最大路径和,来自于左子树+root 或者 右子树+root 或者 root 自身
        int rootMax = Math.max(Math.max(leftMax, rightMax), 0) + root.val;

        //跨节点的最大值,要比较全局最大值的时候需要考虑这种跨节点的情况
        int noRootMax = leftMax + rightMax + root.val;

        GLOBAL_MAX_VALUE = Math.max(Math.max(rootMax, noRootMax), GLOBAL_MAX_VALUE);

        //该递归方法的定义是计算该root节点下单向路径的最大值,不需要考虑跨节点的情况
        return rootMax;
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值