题目描述:
给定一个二叉树,找到其中最大的二叉搜索树(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;//返回
}
};