二叉树中的最大路径和
leetcode题号:124
leetcode链接:https://leetcode.cn/problems/binary-tree-maximum-path-sum/
Note
根据题意,该题为二叉树且路径定义中说明一个节点在一路径中只能出现一次,则可知,任意选中二叉树中的某个节点作为路径起点,例如上图中,若选择节点 2 2 2作为起点,则接下来的路径要么向上或者向下,若向下的话,则路径中的节点要么是 4 4 4或者是 5 5 5,无论是哪一个,根据一个节点在一个路径中只能出现一次的原则,那么该路径将不可再向上,也就是此路径中节点 2 2 2为层次最小且唯一最小的节点;若向上的话,则寻找其父节点 1 1 1,此处节点 1 1 1没有父节点,则路径不可再向上,必须向下,则此时节点1为层次最小且唯一最小的节点;若节点 1 1 1存在父节点,则路径也可以继续向上。以此类推可知,任意路径中必存在一个且唯一的层次最小的节点。
根据这个唯一存在的层次最小的节点,其左右子树中的节点都有可能在某一路径中,而且在一个路径中,除了这个层次最小的节点以外,其他节点的左右子节点若有也必然只会有一个存在于路劲中,例如若节点 1 1 1为某路径中层次最小的节点,则节点 2 2 2的子节点 4 4 4和 5 5 5只会有一个存在于该路径中。
根据以上说明,我们可以从唯一的层次最小的节点出发,遍历当二叉树中的每个节点都作为层次最小的节点的时候的最大路径和,最后再在其中寻找最大值以得到答案。当二叉树中的某个节点作为层次最小的节点的时候,我们则采取后序遍历的方法,先遍历其左右子树,再结合自身值来算出某个路径的路径和。
C++代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int ans = INT_MIN;
int oneSideMax(TreeNode* root) {
if (root == nullptr) return 0;
int leftMax = max(0, oneSideMax(root->left));
int rightMax = max(0, oneSideMax(root->right));
ans = max (ans, leftMax + rightMax + root->val);
return max(leftMax, rightMax) + root->val;
}
int maxPathSum(TreeNode* root) {
oneSideMax(root);
return ans;
}
};
oneSideMax
函数说明(以实例二叉树为具体例子):
- 根据二叉树的根节点,若为空二叉树则直接返回 0 0 0,若为非空则继续,此处为节点 1 1 1;
- 节点 1 1 1的左子节点 2 2 2;
- 节点
2
2
2的左子节点
4
4
4,因为其没有子节点,故其
leftMax
和rightMax
的值都为 0 0 0,此时计算ans
,结果为 4 4 4(此处的结果 4 4 4有另一个含义,便是若把节点 4 4 4当作路径中层次最小的节点的时候的最大路径和),同时返回当节点 4 4 4作为非层次最小的路径节点且包含其左右子树中某一枝时候的总和值,此处仅返回自身的值 4 4 4; - 根据
S
t
e
p
3
Step3
Step3的返回值,继续
S
t
e
p
2
Step2
Step2,节点
2
2
2的
leftMax
的值为 4 4 4,同 S t e p 3 Step3 Step3,可得节点 2 2 2的rightMax
的值都为 5 5 5,此时计算ans
,结果为 11 11 11(这个 11 11 11的结果同样已经把当把节点 2 2 2作为路径中层次最小的节点的时候的最大路径和算出来了,便是 11 11 11。),同时返回当节点 2 2 2作为非层次最小的路径节点且包含其左右子树中某一枝时候的总和值,此处需要比较一下 2 + 4 2+4 2+4和 2 + 5 2+5 2+5哪一个大,故此处仅返回 7 7 7; - 根据
S
t
e
p
4
Step4
Step4的返回值,继续
S
t
e
p
1
Step1
Step1,节点
1
1
1的
leftMax
的值为 7 7 7; - 节点
1
1
1的右子节点
3
3
3,同
S
t
e
p
3
Step3
Step3和
S
t
e
p
4
Step4
Step4,返回结果,故节点
1
1
1的
rightMax
的值为 10 10 10(其中,当把节点 3 3 3作为路径中层次最小的节点的时候的最大路径和也已经算出来了,结果为 16 16 16); - 更新
ans
的结果,为 18 18 18,即该二叉树中的最大路径和。
Python代码:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
ans = -sys.maxsize - 1
def oneSideMax(node: Optional[TreeNode]) -> int:
nonlocal ans
if node == None:
return 0
leftMax = max(0, oneSideMax(node.left))
rightMax = max(0, oneSideMax(node.right))
ans = max(ans, leftMax + rightMax + node.val)
return max(leftMax, rightMax) + node.val
oneSideMax(root)
return ans
Python Note:
- sys.maxsize为当前系统架构中的最大值,使用的话需要import sys,在32位系统中为 2 31 − 1 2^{31}-1 231−1,64位系统中为 2 63 − 1 2^{63}-1 263−1;
- Python中函数可以嵌套定义,在函数中定义的函数,只能在该函数中调用;
- 若要在函数中使用全局变量,则需要在函数中用
nonlocal
声明非局部变量,之后才可以使用。