题目链接
Leetcode.1373 二叉搜索子树的最大键值和 Rating : 1914
题目描述
给你一棵以 r o o t root root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。
二叉搜索树的定义如下:
- 任意节点的左子树中的键值都 小于 此节点的键值。
- 任意节点的右子树中的键值都 大于 此节点的键值。
- 任意节点的左子树和右子树都是二叉搜索树。
示例 1:
输入:root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]
输出:20
解释:键值为 3 的子树是和最大的二叉搜索树。
示例 2:
输入:root = [4,3,null,1,2]
输出:2
解释:键值为 2 的单节点子树是和最大的二叉搜索树。
示例3:
输入:root = [-4,-2,-5]
输出:0
解释:所有节点键值都为负数,和最大的二叉搜索树为空。
示例4:
输入:root = [2,1,3]
输出:6
提示:
- 每棵树有 1 到 40000 个节点。
- 每个节点的键值在 [ − 4 ∗ 1 0 4 , 4 ∗ 1 0 4 ] [-4 * 10^4 , 4 * 10^4] [−4∗104,4∗104] 之间。
解法:dfs
定义 d f s dfs dfs 函数,每次返回这样的一个元组 { 左子树的最大值 l _ m a x , 右子树的最小值 r _ m i n , 子树和 } \{ 左子树的最大值 l\_max,右子树的最小值r\_min,子树和\} {左子树的最大值l_max,右子树的最小值r_min,子树和}。
对于当前节点 r o o t root root 来说,如果 r o o t − > v a l ≤ 左子树的最大值 root->val \leq 左子树的最大值 root−>val≤左子树的最大值 或者 r o o t − > v a l ≥ 右子树的最小值 root->val \geq 右子树的最小值 root−>val≥右子树的最小值,说明该节点无法形成一棵二叉搜索树;
定义
{
l
_
m
a
x
,
l
_
m
i
n
,
l
_
s
u
m
}
\{ l\_max,l\_min,l\_sum \}
{l_max,l_min,l_sum} 为
d
f
s
(
r
o
o
t
−
>
l
e
f
t
)
dfs(root->left)
dfs(root−>left) 的结果;
定义
{
r
_
m
a
x
,
r
_
m
i
n
,
r
_
s
u
m
}
\{ r\_max,r\_min,r\_sum \}
{r_max,r_min,r_sum} 为
d
f
s
(
r
o
o
t
−
>
r
i
g
h
t
)
dfs(root->right)
dfs(root−>right) 的结果;
对于当前节点
r
o
o
t
root
root 来说,如果
r
o
o
t
−
>
v
a
l
≤
左子树的最大值
root->val \leq 左子树的最大值
root−>val≤左子树的最大值 或者
r
o
o
t
−
>
v
a
l
≥
右子树的最小值
root->val \geq 右子树的最小值
root−>val≥右子树的最小值,说明该节点无法形成一棵二叉搜索树;即
r
o
o
t
−
>
v
a
l
≤
l
_
m
a
x
root->val \leq l\_max
root−>val≤l_max 或者
r
o
o
t
−
>
v
a
l
≥
r
_
m
i
n
root->val \geq r\_min
root−>val≥r_min;
这时只能返回
{
I
N
T
_
M
I
N
,
I
N
T
_
M
I
N
,
0
}
\{ INT\_MIN,INT\_MIN,0\}
{INT_MIN,INT_MIN,0}。
否则说明可以形成二叉搜索树,则以 r o o t root root 为根节点的子树和 s u m = l _ s u m + r _ s u m + r o o t − > v a l sum = l\_sum + r\_sum + root->val sum=l_sum+r_sum+root−>val;更新最大答案即可。
最后返回 { m a x ( l _ m a x , r o o t − > v a l ) , m i n ( r _ m i n , r o o t − > v a l ) , s u m } \{max(l\_max , root->val) , min(r\_min , root->val) , sum\} {max(l_max,root−>val),min(r_min,root−>val),sum}。
时间复杂度: O ( n ) O(n) O(n)
C++代码:
class Solution {
int ans = 0; // 二叉搜索树可以为空
tuple<int, int, int> dfs(TreeNode *root) {
if (root == nullptr)
return {0,INT_MAX, INT_MIN};
auto [l_sum , l_min , l_max] = dfs(root->left);
auto [r_sum , r_min , r_max] = dfs(root->right);
int x = root->val;
if (x <= l_max || x >= r_min)
return {0,INT_MIN, INT_MAX};
int sum = l_sum + r_sum + x; // 这棵子树的所有节点值之和
ans = max(ans, sum);
return {sum,min(l_min, x), max(r_max, x)};
}
public:
int maxSumBST(TreeNode *root) {
dfs(root);
return ans;
}
};