98. Validate Binary Search Tree 和延伸

这道题前几遍刷的时候,说实话都没有太搞清楚。导致有两个on site都栽在了这道题上,悔得肠子都青了。


首先来说最简单的解法。因为要验证的树是BST,那个当我们pre-order遍历的时候,得到的结果将会是一个升序数组。所以每访问到一节点,我们只用判断当前节点是不是大于上一个访问的节点的值就可以了。

需要注意的是,如果维护一个vector<int>保存所有之前访问过的节点的值,那么只用int类型的变量就能解决这个问题,代价就是引进了O(n)的空间复杂度。当然也有这种的办法,就是只用vector<int>的第一个元素记录pre的值,那个就不用担心初始化了。不过这个方法有点非主流。我就随便摘一种写一下,代表pre-order这一大类解法。

class Solution {
private:
    long long pre=-100000000000;
public:
    bool isValidBST(TreeNode* root) {
        if(root==nullptr)
            return true;
        if(!isValidBST(root->left))
            return false;
        if(root->val<=pre)
            return false;
        else
            pre=root->val;
        if(!isValidBST(root->right))
            return false;
        return true;
    }
};



第二种解法就是限制每一个subtree的上下界。这是比较普遍的一种做法。这种解法也有需要初始化上下界包含INT_MIN~INT_MAX的情况。我们还可以再多设置两个变量表示INT_MAX和INT_MIN是否出现过。

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        return helper(root, INT_MIN, INT_MAX, false, false);
    }
    
    bool helper(TreeNode* root, int left_max, int right_min, int seen_min, int seen_max){
        if(root==nullptr)
            return true;
        if(root->val==INT_MIN){
            if(seen_min) 
                return false;
            else
                seen_min=true;
        }
        if(root->val==INT_MAX){
            if(seen_max) 
                return false;
            else
                seen_max=true;
        }
        
        return ((left_max<root->val||(root->val==INT_MIN&&left_max==INT_MIN))&&
                (right_min>root->val||(root->val==INT_MAX&&right_min==INT_MAX))&&
                helper(root->left, left_max, root->val, seen_min, seen_max)&&
                helper(root->right, root->val, right_min, seen_min, seen_max));
        
    }
};


第三种解法我把他叫返回值法。就是每遍历一个subtree,都返回一个datadum表示这个subtree的特性。当前树的特性根据左子树datadum,右子树datadum和根节点整理完成。

class Datadum{
public:
    long long min;
    long long max;
    bool valid;
    Datadum(long long x, long long y, bool z){
        min=x;
        max=y;
        valid=z;
    }
};
 
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        Datadum res=helper(root);
        return res.valid;
    }
    
    Datadum helper(TreeNode* root){
        if(root==nullptr){
            return Datadum(2147483649, -2147483649, true);
        }
        Datadum left = helper(root->left);
        Datadum right = helper(root->right);
        if(left.valid==false||right.valid==false||
           root->val<=left.max||root->val>=right.min){
               return Datadum(-2147483649, 2147483649,  false);
           }
        //cout<<root->val<<" "<<min(left.min, root->val)<<" "<<max(right.max,root->val)<<endl;
        long long left_val=left.min<root->val?left.min:root->val;
        long long right_val=right.max>root->val?right.max:root->val;
        return Datadum(left_val, right_val, true);
    }
};

这种做法的用时有点慢,对于这道题非常不推荐这种做法。但是搞明白这种解法,这道题的一些衍生题也就迎刃而解了。

比如 333 largest BST subtree 和最长连续子序列只需要对上文的返回值方法做一点点微小的修改。大致思路不变,在datadum种再添加一个参数就可以了。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值