Skip to content

Commit f637874

Browse files
committed
124
1 parent 83020b8 commit f637874

File tree

3 files changed

+112
-3
lines changed

3 files changed

+112
-3
lines changed

SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
* [99. Recover Binary Search Tree](leetcode-99-Recover-Binary-Search-Tree.md)
103103
* [100. Same Tree](leetcode-100-Same-Tree.md)
104104
* [leetcode 100 斩!回顾](leetcode100斩回顾.md)
105-
* [101 题到 123](leetcode-101-200.md)
105+
* [101 题到 124](leetcode-101-200.md)
106106
* [101. Symmetric Tree](leetcode-101-Symmetric-Tree.md)
107107
* [102. Binary Tree Level Order Traversal](leetcode-102-Binary-Tree-Level-Order-Traversal.md)
108108
* [103. Binary Tree Zigzag Level Order Traversal](leetcode-103-Binary-Tree-Zigzag-Level-Order-Traversal.md)
@@ -125,4 +125,5 @@
125125
* [120. Triangle](leetcode-120-Triangle.md)
126126
* [121. Best Time to Buy and Sell Stock](leetcode-121-Best-Time-to-Buy-and-Sell-Stock.md)
127127
* [122. Best Time to Buy and Sell Stock II](leetcode-122-Best-Time-to-Buy-and-Sell-StockII.md)
128-
* [123*. Best Time to Buy and Sell Stock III](leetcode-123-Best-Time-to-Buy-and-Sell-StockIII.md)
128+
* [123*. Best Time to Buy and Sell Stock III](leetcode-123-Best-Time-to-Buy-and-Sell-StockIII.md)
129+
* [124*. Binary Tree Maximum Path Sum](leetcode-124-Binary-Tree-Maximum-Path-Sum.md)

leetcode-101-200.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@
4242

4343
<a href="leetcode-122-Best-Time-to-Buy-and-Sell-StockII.html">122. Best Time to Buy and Sell Stock II</a>
4444

45-
<a href="leetcode-123-Best-Time-to-Buy-and-Sell-StockIII.html">123. Best Time to Buy and Sell Stock III</a>
45+
<a href="leetcode-123-Best-Time-to-Buy-and-Sell-StockIII.html">123. Best Time to Buy and Sell Stock III</a>
46+
47+
<a href="leetcode-124-Binary-Tree-Maximum-Path-Sum.html">124. Binary Tree Maximum Path Sum</a>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# 题目描述(困难难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/124.jpg)
4+
5+
考虑一条路径,可以从任意节点开始,每个节点最多经过一次,问经过的节点的和最大是多少。
6+
7+
# 解法一 递归
8+
9+
参考了 [这里](<https://leetcode.com/problems/binary-tree-maximum-path-sum/discuss/39875/Elegant-Java-solution>)
10+
11+
首先看到二叉树的题,肯定就是想递归了。递归常规的思路,肯定是递归考虑左子树的最大值,递归考虑右子树的最大值。
12+
13+
```java
14+
public int maxPathSum(TreeNode root) {
15+
if (root == null) {
16+
return Integer.MIN_VALUE;
17+
}
18+
//左子树的最大值
19+
int left = maxPathSum(root.left);
20+
//右子树的最大值
21+
int right = maxPathSum(root.right);
22+
//再考虑包含根节点的最大值
23+
int all = ....;
24+
return Math.max(Math.max(left, right), all);
25+
}
26+
```
27+
28+
问题就来了,怎么考虑包含根节点的最大路径等于多少?因为我们递归求出来的最大 `left` 可能不包含根节点的左孩子,例如下边的情况。
29+
30+
```java
31+
8
32+
/ \
33+
-3 7
34+
/ \
35+
1 4
36+
```
37+
38+
左子树的最大值 `left` 肯定就是 `4` 了,然而此时的根节点 `8` 并不能直接和 `4` 去相连。所以考虑包含根节点的路径的最大值时,并不能单纯的用 `root.val + left + right`
39+
40+
所以如果考虑包含当前根节点的 `8` 的最大路径,首先必须包含左右孩子,其次每次遇到一个分叉,就要选择能产生更大的值的路径。例如下边的例子:
41+
42+
```java
43+
8
44+
/ \
45+
-3 7
46+
/ \
47+
1 4
48+
\ / \
49+
3 2 6
50+
51+
考虑左子树 -3 的路径的时候,我们有左子树 1 和右子树 4 的选择,但我们不能同时选择
52+
如果同时选了,路径就是 ... -> 1 -> -3 -> 4 -> ... 就无法通过根节点 8
53+
所以我们只能去求左子树能返回的最大值,右子树能返回的最大值,选一个较大的
54+
```
55+
假设我们只考虑通过根节点 `8` 的最大路径是多少,那么代码就可以写出来了。
56+
57+
```java
58+
59+
public int maxPathSum(TreeNode root) {
60+
//如果最大值是负数,我们选择不选
61+
int left = Math.max(helper(root.left), 0);
62+
int right = Math.max(helper(root.right), 0);
63+
return root.val + left + right;
64+
}
65+
66+
int helper(TreeNode root) {
67+
if (root == null) return 0;
68+
int left = Math.max(helper(root.left), 0);
69+
int right = Math.max(helper(root.right), 0);
70+
//选择左子树和右子树产生的值较大的一个
71+
return root.val + Math.max(left, right);
72+
}
73+
74+
```
75+
76+
接下来我觉得就是这道题最精彩的地方了,现在我们只考虑了包含最初根节点 `8` 的路径。那如果不包含当前根节点,而是其他的路径呢?
77+
78+
可以发现在 `helper` 函数中,我们每次都求了当前给定的节点的左子树和右子树的最大值,和我们 `maxPathSum` 函数的逻辑是一样的。所以我们利用一个全局变量,在考虑 `helper` 函数中当前 `root` 的时候,同时去判断一下包含当前 `root` 的路径的最大值。
79+
80+
这样在递归过程中就考虑了所有包含当前节点的情况。
81+
82+
```java
83+
int max = Integer.MIN_VALUE;
84+
85+
public int maxPathSum(TreeNode root) {
86+
helper(root);
87+
return max;
88+
}
89+
int helper(TreeNode root) {
90+
if (root == null) return 0;
91+
92+
int left = Math.max(helper(root.left), 0);
93+
int right = Math.max(helper(root.right), 0);
94+
95+
//求的过程中考虑包含当前根节点的最大路径
96+
max = Math.max(max, root.val + left + right);
97+
98+
//只返回包含当前根节点和左子树或者右子树的路径
99+
return root.val + Math.max(left, right);
100+
}
101+
```
102+
103+
#
104+
105+
这道题最妙的地方就是在递归中利用全局变量,来更新最大路径的值,太强了。前边遇到过和全局变量结合的递归,例如 [106 题](<https://leetcode.wang/leetcode-106-Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.html#%E8%A7%A3%E6%B3%95%E4%BA%8C-stop-%E5%80%BC>),当递归和全局变量结合有时候确实会难理解些。而在 [ 110 题](<https://leetcode.wang/leetcode-110-Balanced-Binary-Tree.html>) 中也应用了和这个题一样的思想,就是发现递归过程和主函数有一样的逻辑,此时可以在递归过程中就可以进行求解。
106+

0 commit comments

Comments
 (0)