/**
*
* 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;
}
}
