题目描述
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 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