-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path二叉树最大路径和.cpp
71 lines (56 loc) · 2.58 KB
/
二叉树最大路径和.cpp
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
这题目的难点在于理解题意和转化题意。
我们可以结合 数组的最大子数组和 的思路去解题。
1. 「可以从任意节点出发, 到达任意节点」 的路径,
一定是先上升( 0 ~ n 个)节点, 到达顶点, 后下降( 0 ~ n 个)节点。
我们可以通过枚举顶点的方式来枚举路径。
2. 我们枚举顶点时, 可以把路径分拆成3部分: 左侧路径、右侧路径和顶点。
如下面的路径, 顶点为 20, 左侧路径为 6 -> 15, 右侧为 6 -> 7。
-10
/ \
9 [20]
/ \
[15] [7]
/ / \
[6] 4 [6]
以当前节点为顶点的路径中, 最大和为 两侧路径的最大和 + 节点的值。
需要注意的是, 两侧路径也可能不选, 此时取 0。
3. 如何求两侧路径最大和? 看一个类似问题:求数组的最大子数组和。
动态规划: dp[i] 代表以 nums[i] 为结尾的子数组的最大和。
转移方程: dp[i] = max(dp[i-1], 0) + nums[i]。
4. 在树上, 设 dp[C] 代表以当前节点为结尾的最大上升路径和,
则我们需要对节点的左右子树做一个选择, 有
dp[C] = max(max(dp[L], 0), max(dp[R], 0)) + C.val
式中, C,L,R 分别代指 当前节点、左子节点、右子节点。
5. 最后, 以当前节点为顶点的路径中, 最大的和为
max(dp[L], 0) + max(dp[R], 0) + C.val。
我们枚举顶点, 并记录最大答案。
*/
class Solution {
private:
int maxSum = INT_MIN;
public:
int maxGain(TreeNode* node) {
if (node == nullptr) {
return 0;
}
// 递归计算左右子节点的最大贡献值
// 只有在最大贡献值大于 0 时,才会选取对应子节点
int leftGain = max(maxGain(node->left), 0);
int rightGain = max(maxGain(node->right), 0);
// 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
int priceNewpath = node->val + leftGain + rightGain; // 因为路并非必须从上到下
// 更新答案
maxSum = max(maxSum, priceNewpath);
// 返回节点的最大贡献值
return node->val + max(leftGain, rightGain);
}
int maxPathSum(TreeNode* root) {
maxGain(root);
return maxSum;
}
};
// 作者:LeetCode-Solution
// 链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。