返回
验证二叉搜索树:深入理解BST的性质
后端
2023-12-19 22:04:23
LeetCode 上的二叉搜索树(BST)系列之旅,我们已经探讨了插入、搜索和删除操作。现在,是时候深入了解 BST 的一个关键性质——有序性。这正是「验证二叉搜索树」问题所要解决的。
验证二叉搜索树的性质
BST 的有序性体现在两个方面:
- 左子树上的所有节点值都小于根节点值。
- 右子树上的所有节点值都大于根节点值。
算法实现
中序遍历
验证 BST 的最简单方法之一是中序遍历。中序遍历将节点值按升序排列,因此如果 BST 有序,则中序遍历结果应该是一个有序序列。
def is_valid_bst(root):
# 中序遍历结果
result = []
def traverse(node):
if not node:
return
traverse(node.left)
result.append(node.val)
traverse(node.right)
traverse(root)
# 检查结果是否有序
return result == sorted(result)
递归比较
另一种方法是递归比较每个节点与其子节点的值。如果一个节点的值小于其左子节点或大于其右子节点,则表明该 BST 无序。
def is_valid_bst(root):
# 验证函数
def validate(node, lower, upper):
if not node:
return True
# 当前节点值超出范围
if node.val <= lower or node.val >= upper:
return False
# 递归验证子节点
return validate(node.left, lower, node.val) and validate(node.right, node.val, upper)
# 从最小值和最大值开始验证
return validate(root, float('-inf'), float('inf'))
优化
最大值和最小值跟踪
在递归比较中,每次调用 validate
函数时,都会更新 lower 和 upper 界限。我们可以优化这个过程,通过在每个节点处跟踪子树的最大值和最小值。这样,在验证该节点的子节点时,我们可以直接使用这些值作为界限。
def is_valid_bst(root):
# 节点信息(值、最小值、最大值)
class NodeInfo:
def __init__(self, val, min, max):
self.val = val
self.min = min
self.max = max
def validate(node):
if not node:
return NodeInfo(None, None, None)
# 递归验证子节点
left_info = validate(node.left)
right_info = validate(node.right)
# 检查是否有序
if (left_info.max is None or left_info.max < node.val) and (right_info.min is None or right_info.min > node.val):
return NodeInfo(node.val, left_info.min or node.val, right_info.max or node.val)
else:
return None
# 从根节点开始验证
return validate(root) is not None
其他优化
- 使用堆栈或队列进行迭代而不是递归。
- 利用 BST 的平衡特性,使用分治法。
- 对于大型数据集,考虑使用并行算法。