【Leetcode】98. 验证二叉搜索树

QUESTION

medium

题目描述

给定一个二叉树,判断其是否是一个有效的二叉搜索树

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数
  • 节点的右子树只包含大于当前节点的数
  • 所有左子树和右子树自身必须也是二叉搜索树

示例 1:

输入:
    2
   / \
  1   3
输出: true

示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6],根节点的值为 5 ,但是其右子节点值为 4

说明


SOLUTION

一看到这个题目,第一反应的直接递归判断,使得该结点的键值大于所有左结点的键值,小于所有右结点的键值,这个办法似乎有点麻烦,而且总是感觉有些难以理解,有没有别的办法呢

方法一

按照前面的想法,从根递归下去,判断值,注意要更新每个子树的上下限

bool isValidBST(TreeNode* root) {
    return isValid(root, LONG_MIN, LONG_MAX);
}
bool isValid(TreeNode *root, long mn, long mx) {
    if(!root) return true;
    if(root->val <= mn || root->val >= mx) return false;
    return isValid(root->left, mn, root->val) && isValid(root->right, root->val, mx);
}

方法二(BST中序遍历的性质)

明白一个简单的结论:BST 的中序遍历是严格递增的

bool isValidBST(TreeNode* root) {
    if(!root) return true;
    vector<int> in;
    inorder(root, in);
    if(in.size() == 1) return true;
    else {
        for (int i = 0; i < in.size() - 1; i++)
            if (in[i] >= in[i+1]) return false;
        return true;
    }
}
void inorder(TreeNode *root, vector<int> &in) {
    if (!root) return;
    inorder(root->left, in);
    in.push_back(root->val);
    inorder(root->right, in);
}

这个方法,其实还可以简化,可以不用数组保存,实际上可以在遍历的同时检查是否严格递增,下面这段代码是copy了别人的写法,确实太厉害了(原文:http://www.cnblogs.com/grandyang/p/4297300.html

bool isValidBST(TreeNode* root) {
    TreeNode* pre = NULL;
    return isValid(root, pre);
}
bool isValid(TreeNode* node, TreeNode*& pre){
    if(!node) return true;
    bool left = isValid(node->left, pre);
    if(!left) return false;
    if(pre && node->val <= pre->val) return false;
    pre = node;
    return isValid(node->right, pre);
}

当然既然是中序遍历,那也有不是递归的写法

bool isValidBST(TreeNode* root) {
    stack<TreeNode*> s;
    TreeNode *p = root, *pre = NULL;
    while (p || !s.empty()) {
        while (p) {
            s.push(p);
            p = p->left;
        }
        p = s.top(); s.pop();
        if (pre && p->val <= pre->val) return false;
        pre = p;
        p = p->right;
    }
    return true;
}

上面原文的大佬解释中有非递归非栈的写法,有兴趣的的小伙伴,可以移步围观

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值