给定一个二叉树,找到其中最大的二叉搜索树(BST)子树,并返回该子树的大小。其中,最大指的是子树节点数最多的。
二叉搜索树(BST)中的所有节点都具备以下属性:
左子树的值小于其父(根)节点的值。
右子树的值大于其父(根)节点的值。
注意:
子树必须包含其所有后代。
进阶:
你能想出 O(n) 时间复杂度的解法吗?
示例:
输入:root = [10,5,15,1,8,null,7]
输出:3
解释:本例中最大的 BST 子树是高亮显示的子树。返回值是子树的大小,即 3 。
1.遍历
class Solution {
public:
bool valid(TreeNode* root,int l,int r){
if(root==NULL) return 1;
if(root->val<=l||root->val>=r) return 0;
return valid(root->left,l,root->val)&&valid(root->right,root->val,r);
}
int cnt(TreeNode* root) {
return root?cnt(root->left)+cnt(root->right)+1:0;
}
int largestBSTSubtree(TreeNode* root) {
if(root==NULL) return 0;
if(valid(root,INT_MIN,INT_MAX)) return cnt(root);
return max(largestBSTSubtree(root->left),largestBSTSubtree(root->right));
}
};
我们枚举每个节点需要 O(n)的时间,而检查每个节点为根的子树是不是二叉搜索树需要 O(n)的时间,所以一共需要 O(n^2) 的时间复杂度
2.复用子树信息
struct Node{
int l,r,sz;
};
class Solution{
int ans=0;
public:
int largestBSTSubtree(TreeNode* root){
if(root==NULL) return 0;
dfs(root);
return ans;
}
Node dfs(TreeNode* root){
if(root->left==NULL&&root->right==NULL) {
ans = max(ans,1);
return (Node){root->val,root->val,1};
}
int sz=1;
bool valid=true;
int l=root->val,r=root->val;
if(root->left!=NULL) {
Node L = dfs(root->left);
if(L.sz!=-1&&root->val>L.r) {
sz+=L.sz;
l=L.l;
}else valid=false;
}
if(root->right!=NULL){
Node R = dfs(root->right);
if(R.sz!=-1&&root->val<R.l){
sz+=R.sz;
r=R.r;
}else valid=false;
}
if(valid) {
ans=max(ans,sz);
return (Node){l,r,sz};
}
return (Node){-1,-1,-1};
}
};