echo

任生命穿梭 时间的角落

0%

二叉树中的最大路径和

124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例 1:

1
2
3
4
5
6
7
输入: [1,2,3]

1
/ \
2 3

输出: 6

示例 2:

1
2
3
4
5
6
7
8
9
输入: [-10,9,20,null,null,15,7]

-10
/ \
9 20
/ \
15 7

输出: 42

考虑一个二叉树单元

   |
   a
  / \
 b   c
/ \ / \
  • a 是根结点,与上层得父节点相连(如果存在父节点)
  • b 和 c 是子结点,与各自子节点中路径最大值得结点相连
  • 所有可能得路径情况:
    • 「左中右」b + a + c
    • 「左」b + a
    • 「右」c + a

选择「左」还是「右」:递归调用计算 b 和 c 的最大贡献值,计算 b + a 和 c + a,选择较大的值为返回值,更新到全局最大和。

选择「左中右」:递归调用计算 b 和 c 的最大贡献值,计算 b + a + c 的值,更新到全局最大和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int maxSum = Integer.MIN_VALUE;

public int maxPathSum(TreeNode root) {
maxGain(root);
return maxSum;
}

public int maxGain(TreeNode node){
//结点为空,贡献值为 0
if(node == null){
return 0;
}
//递归计算左右子节点的最大贡献值,只有在最大贡献值大于 0 时,才会选取对应子结点
int left = Math.max(maxGain(node.left), 0);
int right = Math.max(maxGain(node.right), 0);

//选择左中右,计算贡献值并更新最大贡献值
int priceNewPath = node.val + left + right;
maxSum = Math.max(maxSum, priceNewPath);
//选择左或右,选择较大的值返回
return node.val + Math.max(left, right);
}
}

时间复杂度O(N),其中 N 是二叉树中结点个数。对每个结点访问不超过 2 次。

空间复杂度O(N),最坏情况下二叉树退化为链表,递归深度为 N。