题目描述
链接:https://leetcode-cn.com/problems/maximum-sum-bst-in-binary-tree/
给你一棵以 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
示例 5:
输入:root = [5,4,8,3,null,6,3]
输出:7
提示:
每棵树最多有 40000 个节点。
每个节点的键值在 [-4 * 10^4 , 4 * 10^4] 之间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-sum-bst-in-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路分析
这道题比较麻烦的一点是要判断这棵树是不是二叉搜索树。这里我借(chao)鉴(xi)了大佬的做法。这里我们用到了树形dp的做法:先向子树进行递归,递归的过程中判断自己的左右儿子符不符合二叉搜索树的条件。返回的时候,需要返回四个状态:自己符不符合二叉搜索树?目前我这个子树上的最大键值是多少?最小键值是多少(用于给自己的根节点判断符不符合二叉搜索树)?现在的键值和是多少?这里大佬有个技巧:如果需要返回多个值,可以选择返回一个vector记录这些状态。另外,需要要注意遇到NULL节点时的处理。
ac代码
int ans=0;
class Solution {
public:
vector<int> dfs(TreeNode*root)//返回状态、最小值、最大值、和
{
if(root==NULL) return {true,INT_MAX,INT_MIN,0};
vector<int> ar=dfs(root->right);
vector<int> al=dfs(root->left);
if(!ar[0]||!al[0]||root->val<=al[2]||root->val>=ar[1])
{
return {false,0,0,0};
}
int sum=ar[3]+al[3]+root->val;
int maxnn=root->right==NULL?root->val:ar[2];
int minn=root->left==NULL?root->val:al[1];
ans=max(ans,sum);
return {true,minn,maxnn,sum};
}
int maxSumBST(TreeNode* root) {
ans=0;//力扣上定义全局变量需要再初始化一次。
dfs(root);
return ans;
}
};
另外还有一种更好的写法:
dfs的过程中,判断这个子树是否为二叉搜索树,是的话直接求这颗树的键值和,比上面的方法快。
int ans=0;
class Solution {
public:
bool judge(TreeNode*root)
{
int flag1=0,flag2=0;
if(!root->right){
flag1=1;
}
else{
flag1=(root->val<root->right->val)&&judge(root->right);
}
if(!root->left){
flag2=1;
}
else{
flag2=(root->val>root->left->val)&&judge(root->left);
}
//if(root->val==5) cout<<flag1<<" ** "<<flag2<<endl;
//cout<<root->val<<" "<<(flag1&&flag2)<<endl;
return flag2&&flag1;
}
int calculate(TreeNode*root){
if(!root) return 0;
int s1=calculate(root->right);
int s2=calculate(root->left);
ans=max(root->val+s1+s2,ans);
return root->val+s1+s2;
}
void dfs(TreeNode*root){
if(!root) return;
if(!judge(root)){
if(root->right) dfs(root->right);
if(root->left) dfs(root->left);
}
else{
ans=max(ans,calculate(root));
}
}
int maxSumBST(TreeNode* root) {
ans=0;
dfs(root);
return ans;
}
};