算法日记本 | LeetCode 98. 验证二叉搜索树

题目描述

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

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

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

示例 1:

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

示例 2:

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

分析解答

乍一看是道挺简单的题目,二叉搜索树的一个特点是:中序遍历得到的结果是一个递增的数组,直接利用这个结论,通过递归实现一个中序遍历,再遍历一下得到的数组即可:

class Solution(object):
    def __init__(self):
        self.arr = list()

    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        self.middleOrder(root)
        for i in range(len(self.arr) - 1):
            if self.arr[i] >= self.arr[i + 1]:
                return False
        return True

    def middleOrder(self, root):
        if root is None:
            return
        if root.left is None:
            self.arr.append(root.val)
            self.middleOrder(root.right)
        elif root.right is None:
            self.middleOrder(root.left)
            self.arr.append(root.val)
        else:
            self.middleOrder(root.left)
            self.arr.append(root.val)
            self.middleOrder(root.right)

提交结果,验证通过!不过看了眼结果,只超过了7%的提交,有点小忧伤,看来这种方法性能还是比较差的,主要的原因应该有两个:

  • 有些时候其实很早就可以得出否定的结论,比如根节点的值就小于它左边子节点的值,但这种方法一定要将全部节点值遍历之后才能得出结果,增加了平均的时间复杂度。
  • 对数组进行遍历增加了额外的时间开销,实际上可以在递归的过程中一起进行判断,只要我们维护一个当前最后访问到的节点的值即可,这样在遍历时就可以保证有序性,或者在中途不满足条件时直接得到否定的结论。

按照这种思路,可以得到一个更优的中序遍历的实现:

import sys


class Solution(object):
    def __init__(self):
        self.last = sys.float_info.max * -1

    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if root is None:
            return True
        if self.isValidBST(root.left):
            if self.last < root.val:
                self.last = root.val
                return self.isValidBST(root.right)
        return False

这里有个值得注意的点是,最后一次访问到的节点的值必须被初始化为系统最小的浮点数,因为在提交时发现有一个测试用例就是卡在了边界值上 = =,出题人还有点小心机呢哈哈。

重新提交结果,超过80%的提交!Bingo!

今天的分享就到这啦,让我们相约下一题吧!


以上就是本文的全部内容,如果您喜欢这篇文章,欢迎将它分享给朋友们。

感谢您的阅读,祝您生活愉快!

作者:小美哥
2019-03-15

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值