给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
思路:
二叉搜索树:左子树的所有节点都小于根节点,右子树的所有节点都大于根节点。左子树和右子树也是如此。
二叉搜索树:中序遍历(左中右),元素是有序的!
方法:
方法一:先把二叉树遍历下来,再判断是否是从小到大有序的。(这不是最优的方法,其实没必要把元素都存下来,直接在遍历二叉树的时候就可以判断是否单调递增)
方法二:
注意:不仅仅是判断root比左孩子大,比右孩子小。而是root要比左子树里面所有节点都大,比右子树里所有节点都小!
代码:
递归法(版本一):利用中序递增性质,转换成数组
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.vec = []
def traversal(self, root):
if root is None:
return
self.traversal(root.left)
self.vec.append(root.val) # 将二叉搜索树转换为有序数组
self.traversal(root.right)
def isValidBST(self, root):
self.vec = [] # 清空数组
self.traversal(root)
for i in range(1, len(self.vec)):
# 注意要小于等于,搜索树里不能有相同元素
if self.vec[i] <= self.vec[i - 1]:
return False
return True
递归法(版本二):设定极小值,进行比较
class Solution:
def __init__(self):
# 初始化 maxVal 为负无穷大,这是为了确保在比较时能够正确处理所有可能的节点值
self.maxVal = float('-inf')
def isValidBST(self, root):
# 检查当前节点是否为空
if root is None:
# 如果当前节点为空,返回 True,表示空树是有效的二叉搜索树(BST)
return True
# 递归调用 isValidBST 函数检查左子树是否是有效的 BST
left = self.isValidBST(root.left)
# 中序遍历,验证遍历的元素是否按升序排列
# 检查当前节点的值是否大于 self.maxVal
if self.maxVal < root.val:
# 如果当前节点的值大于 self.maxVal,则更新 self.maxVal 为当前节点的值
self.maxVal = root.val
else:
# 如果当前节点的值不大于 self.maxVal,说明树不是有效的 BST
return False
# 递归调用 isValidBST 函数检查右子树是否是有效的 BST
right = self.isValidBST(root.right)
# 返回左子树和右子树的检查结果,只有当左右子树都是有效的 BST 时,返回 True
return left and right
(讲解:
因为是按照中序遍历:左中右,所以遍历过程中,每一个遍历到的值,都应该比之前遍历的值中的最大值更大。所以,如果当前节点的值不大于self.maxVal,说明树不是有效的BST,return False。otherwise,就继续递归遍历。)