333最大BST子树

给定一个二叉树,找到其中最大的二叉搜索树(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};
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值