前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leetcode刷题(21)——98. 验证二叉搜索树

leetcode刷题(21)——98. 验证二叉搜索树

作者头像
老马的编程之旅
发布2022-06-22 13:26:49
1630
发布2022-06-22 13:26:49
举报
文章被收录于专栏:深入理解Android

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

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

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

代码语言:javascript
复制
输入:
    2
   / \
  1   3
输出: true

示例 2:

代码语言:javascript
复制
输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4 。

坑爹之处:乍一看,这是一个平凡的问题。只需要遍历整棵树,检查 node.right.val > node.val 和 node.left.val < node.val 对每个结点是否成立。 于是我做了如下的写法:

代码语言:javascript
复制
class Solution {

        public boolean isValidBST(TreeNode root) {
            if (root == null) {
                return true;
            }
            if (isValid(root)) {
                return isValidBST(root.left) && isValidBST(root.right);
            }
            return false;
        }

        public boolean isValid(TreeNode root) {
            if (root.left == null && root.right == null) {
                return true;
            } else if (root.left == null) {
                if (root.right.val > root.val) {
                    return true;
                }
            } else if (root.right == null) {
                if (root.left.val < root.val) {
                    return true;
                }
            } else {
                return root.val < root.right.val && root.val > root.left.val;
            }
            return false;
        }
    }

**问题是,这种方法并不总是正确。不仅右子结点要大于该节点,整个右子树的元素都应该大于该节点。**例如: 这意味着我们需要在遍历树的同时保留结点的上界与下界,在比较时不仅比较子结点的值,也要与上下界比较。

方法一: 递归

代码语言:javascript
复制
class Solution {
    
    public boolean isValidBST(TreeNode root) {
         
        return isValid(root,null,null);
    }
    
    public boolean isValid(TreeNode root,Integer lower,Integer upper){
        if (root == null) return true;
        int value = root.val;
        if(lower!=null&&value<=lower){
            return false;
        }
        if(upper!=null&&value>=upper){
            return false;
        }
        if(!isValid(root.right,value,upper)){
            return false;
        }
        if(!isValid(root.left,lower,value)){
            return false;
        }
        return true;
    }

方法二:中序遍历 左子树 -> 结点 -> 右子树的顺序。 左子树 -> 结点 -> 右子树 意味着对于二叉搜索树而言,每个元素都应该比下一个元素小。

因此,具有 {O}(N)O(N) 时间复杂度与 {O}(N)O(N) 空间复杂度的算法十分简单:

计算中序遍历列表 inorder.

检查 inorder中的每个元素是否小于下一个。

事实上不需要。因此,我们可以将步骤整合并复用空间。

代码语言:javascript
复制
class Solution {
  public boolean isValidBST(TreeNode root) {
    Stack<TreeNode> stack = new Stack();
    double inorder = - Double.MAX_VALUE;

    while (!stack.isEmpty() || root != null) {
      while (root != null) {
        stack.push(root);
        root = root.left;
      }
      root = stack.pop();
      // If next element in inorder traversal
      // is smaller than the previous one
      // that's not BST.
      if (root.val <= inorder) return false;
      inorder = root.val;
      root = root.right;
    }
    return true;
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档