最大二叉搜索子树问题


【题目】

有一棵二叉树,其中所有节点的值都不一样,找到含有节点最多 的搜索二叉子树,并返回这棵子树的头节点.
给定二叉树的头结点root,请返回所求的头结点,若出现多个节点最多的子树,返回头结点权值最大的。


【分析】

最大二叉搜索子树,我们只需要使用三个变量保存每个结点为根的子树的min,max,以及它对应的最大二叉搜索子树的结点数目。然后判断是否更新即可。

注意两点:(左半部分最大值用lmax表示,右半部分最小值用rmin表示,t表示当前根节点)

  1. 如果lmax < t->val < rmin,那么以该结点为根的子树更新为最大二叉搜索子树,最大二叉搜索子树的数目等于左数目+1(自己)+右数目。
  2. 如不满足1,那就找出左右数目最大的返回即可,继续寻找,并判断是否更新。

【代码】
class MaxSubtree {
public:
    TreeNode* getMax(TreeNode* root) {
        assert(root != nullptr);
        vector<int> res(3, 0); 
        return get_max_detail(root, res);
    }
private:
    TreeNode* get_max_detail(TreeNode* t, vector<int>& res){
        if(t == nullptr){ //res[0] means min, res[1] means max, res[2] means counter of BST tree node
            res[0] = INT_MAX;
            res[1] = INT_MIN;
            res[2] = 0;
            return nullptr;
        }
        
        int lmin = 0, lmax = 0, lcnt = 0;
        TreeNode* lnode = get_max_detail(t->left, res);
        lmin = res[0];
        lmax = res[1];
        lcnt = res[2];
           
        TreeNode* rnode = get_max_detail(t->right, res);
        
        //don't do like (lnode==null && rnode==null) || (lmax<t->val && rmax>t->val)
        //because the lnode or rnoe maybe not the child of the "t".
        if((lnode == t->left && rnode == t->right) 
           && (lmax < t->val && res[0] > t->val)){    //update
            res[0] = std::min(lmin, t->val);
            res[1] = std::max(res[1], t->val);
            res[2] = lcnt + res[2] + 1;
            return t;
        }
        
        if(lcnt > res[2]){
            //res[0] = lmin;    //this line deleted is also ok
            //res[1] = lmax;   //this line deleted is also ok
            res[2] = lcnt;
            return lnode;
        }
        else
            return rnode;
    }
};
这道题难点在叶子结点的情况,刚开始我处理方式是如图注释中那种情况,没有考虑到如果最大二叉搜索子树不是连续的,即最大二叉搜索子树在某个结点1断开,可能当时最大的二叉搜索子树是结点1的左孩子拥有的子树X(不包括结点1),继续向根部回溯后,出现另外一个右分支中的最大二叉搜索子树Y,它的根的父亲不是结点1,此时如果子树X的最大值 < t->val < 子树Y的最小值, 这样新合成一个包括断点,以及中间可能多个不连续的点的新最大二叉搜索子树,这是错误的

所以,需要用(lnode==t->left && rnode==t->right && ...)作为判断条件。

值得注意的是,最后有两句话是可以去掉的。因为出现那种情况,等于出现了断层。以后只需要比较它们的数目,不关心它们的min和max了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值