333 最大 BST 子树

题目描述:
给定一个二叉树,找到其中最大的二叉搜索树(BST)子树,其中最大指的是子树节点数最多的。
注意:
子树必须包含其所有后代。

示例:
输入: [10,5,15,1,8,null,7]
在这里插入图片描述
输出: 3
解释: 高亮部分为最大的 BST 子树。
返回值 3 在这个样例中为子树大小。

进阶:
你能想出用 O(n) 的时间复杂度解决这个问题吗?

方法1:
主要思路:
(1)自定向下,使用当前结点一定是左子树中的最大值,一定是右子树中的最小值的特点,递归遍历;
(2)当找到满足要求的结点,返回结点值;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int largestBSTSubtree(TreeNode* root) {
        if(root==NULL){
            return 0;
        }
        //判断当前结点作为根节点,是否满足搜索树的要求
        if(is_valid(root,INT_MIN,INT_MAX)){
            return count(root);
        }
        //否则,返回左右子树中可能的最大值
        return max(largestBSTSubtree(root->left),largestBSTSubtree(root->right));
    }
    //判断当前子树是否是二叉搜索树
    bool is_valid(TreeNode* root,int min_val,int max_val){
        if(root==NULL){
            return true;
        }
        //结点值不满足要求
        if(root->val<=min_val||root->val>=max_val){
            return false;
        }
        //递归
        return is_valid(root->left,min_val,root->val)&&is_valid(root->right,root->val,max_val);
    }
    //找出当前结点作为根节点时,子树的结点数量
    int count(TreeNode* root){
        if(root==NULL){
            return 0;
        }
        return count(root->left)+count(root->right)+1;
    }
};

方法2:
主要思路:
(1)自底向上;
(2)将需要的变量定义为结构体;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    struct Min_max{
        int min_val;//子树中的最大值
        int max_val;//子数中的最小值
        int size;//子树的大小
        bool sign;//子树是否是二叉搜索树
        Min_max():min_val(INT_MAX),max_val(INT_MIN),size(0),sign(true){}//初始化值
    };

    int largestBSTSubtree(TreeNode* root) {
        Min_max m=helper(root);
        return m.size;
    }

    Min_max helper(TreeNode* root){
        if(root==NULL){//终止
            return Min_max();
        }
        //左右子树
        Min_max left_minmax=helper(root->left);
        Min_max right_minmax=helper(root->right);
        //根据左右子树的状态,计算当前结点的状态
        Min_max m_val=Min_max();
        //该节点不能组成二叉搜索树
        if(!left_minmax.sign||!right_minmax.sign||left_minmax.max_val>=root->val||right_minmax.min_val<=root->val){
        	//则返回之前已经找到的子树的状态即可
            m_val.size=max(left_minmax.size,right_minmax.size);
            m_val.sign=false;
            return m_val;
        }
        //当前结点能够组成二叉搜索树
        m_val.sign=true;
        m_val.size=left_minmax.size+right_minmax.size+1;//更新数的结点的数量
		
		//更新当前结点中的最小和最大值
        m_val.min_val=root->left!=NULL?left_minmax.min_val:root->val;
        m_val.max_val=root->right!=NULL?right_minmax.max_val:root->val;

        return m_val;//返回
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值