LeetCodeAnimation/0124-Binary-Tree-Maximum-Path-Sum/Article/0124-Binary-Tree-Maximum-Path-Sum.md

97 lines
3.9 KiB
Java
Raw Normal View History

2020-04-17 12:16:32 +08:00
# LeetCode 124 号问题二叉树中的最大路径和
> 本文首发于公众号图解面试算法 [图解 LeetCode](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步博客https://www.algomooc.com
题目来源于 LeetCode 上第 124 号问题二叉树中的最大路径和题目难度为 Hard目前通过率为 39.9%
<br>
### 题目描述
给定一个非空二叉树返回其最大路径和
本题中路径被定义为一条从树中任意节点出发达到任意节点的序列该路径至少包含一个节点且不一定经过根节点
**示例 1:**
```
输入: [1,2,3]
1
/ \
2 3
输出: 6
```
**示例 2:**
```
输入: [-10,9,20,null,null,15,7]
-10
/ \
9 20
/ \
15 7
输出: 42
```
<br>
### 题目解析
二叉树问题题目要求出一个二叉树的最大路径和路径和就是把一条路径上面节点的值加起来这一题的难点在于路径的方向不固定只要是任意两点间的通路都算是有效路径如果不提前列出合理的规划这道题将无从下手一般来说解决树的问题都需要用到递归**树上的搜索本质上也是深度优先搜索**但是这里会有两种考虑方式一个是**自底向上的分治**也就是进入递归一开始不做任何节点上面的计算或者是处理直接进入到下一层递归直到到了最底层然后再开始计算并返回答案然后上层树节点的递归函数就会收到下层返回的结果这样做的好处是一个节点可以获知其子树的局部答案另外一个是**自顶向下的遍历搜索**这个和之前的思路完全相反也就是先处理当前节点的内容处理完后去到下一层节点这种方法一般没有返回值但是一般会有一个全局或者是引用变量用来记录遍历过程中的内容
我们再回过头来看这道题在递归遍历的过程中对于当前节点其在路径中可以是路径尾路径头假设路径是从上到下的其实在这道题中没有头尾的概念也可以是路径中的一个节点那怎么判断呢这时我们得需要当前节点左右子树的信息所以我们可以考虑使用之前提到的 **自底向上** 的分治有了当前节点左右子树到当前节点的最大路径我们可以看看这里会有几种情况我用 **root** 表示当前节点**left** 表示左子树到 root 的最大和的路径**right** 表示右子树到 root 的最大和的路径
* root 和左右路径形成路径left - root - right
* root 和左路径形成路径left - root
* root 和右路径形成路径root - right
* root 自成路径root
你可以看到这四种情况都会把当前节点考虑在内我们可以更新这里的最大值但是需要注意的是我们返回的时候第一种情况是不能返回的因为对于上一层节点来说其无法形成有效的路径因此我们只需要将 234 中的最大值返回即可当然更新全局答案的时候 4 种情况都需要考虑在内的
<br>
### 代码实现
```java
private int maximum = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
if (root == null) {
return 0;
}
helper(root);
return maximum;
}
private int helper(TreeNode root) {
if (root == null) {
return 0;
}
// 如果左右子树返回的最大路径值小于 0
// 直接将值设为 0也就是不考虑对应的路径
int leftMax = Math.max(0, helper(root.left));
int rightMax = Math.max(0, helper(root.right));
maximum = Math.max(root.val + leftMax + rightMax, maximum);
return Math.max(leftMax + root.val, rightMax + root.val);
}
```
<br>
### 动画描述
![](../Animation/124.gif)
![](../../Pictures/qrcode.jpg)