Validate Binary Search Tree
Initialize previous value to negative infinity
We start by setting prev to negative infinity to ensure the first node's value will be greater.
prev = [float('-inf')]Start inorder traversal at root node (2)
Begin recursion by calling inorder on the root node with value 2.
return inorder(root)Traverse left subtree of node 2
Recursively call inorder on the left child of node 2, which is node 1.
if not inorder(node.left):
return FalseCheck left child node 1 against prev
Since node 1 has no left child, we check if its value (1) is greater than prev (-inf).
if node.val <= prev[0]:
return False
prev[0] = node.valTraverse right subtree of node 1 (null)
Call inorder on the right child of node 1, which is null, so return True immediately.
if not node:
return TrueReturn from node 1 to node 2
Finished processing node 1, return True to node 2 to continue traversal.
return inorder(node.right)Check node 2 value against prev
Compare node 2's value (2) with prev (1) to ensure BST property holds.
if node.val <= prev[0]:
return False
prev[0] = node.valTraverse right subtree of node 2
Recursively call inorder on the right child of node 2, which is node 3.
return inorder(node.right)Traverse left subtree of node 3 (null)
Call inorder on left child of node 3, which is null, so return True immediately.
if not node:
return TrueCheck node 3 value against prev
Compare node 3's value (3) with prev (2) to ensure BST property holds.
if node.val <= prev[0]:
return False
prev[0] = node.valTraverse right subtree of node 3 (null)
Call inorder on right child of node 3, which is null, so return True immediately.
if not node:
return TrueReturn from node 3 to node 2
Finished processing node 3, return True to node 2 to complete traversal.
return inorder(node.right)Return final result true
The entire inorder traversal completed without violations, so return True as the BST validation result.
return inorder(root)class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def is_valid_bst(root):
prev = [float('-inf')] # STEP 1
def inorder(node):
if not node: # STEP 5, 9, 11
return True
if not inorder(node.left): # STEP 3
return False
if node.val <= prev[0]: # STEP 4, 7, 10
return False
prev[0] = node.val # STEP 4, 7, 10
return inorder(node.right) # STEP 5, 8, 11
return inorder(root) # STEP 2, 13
if __name__ == '__main__':
root = TreeNode(2, TreeNode(1), TreeNode(3))
print(is_valid_bst(root)) # TrueKey Takeaways
This insight is hard to see from code alone but becomes obvious when watching the traversal order and comparisons.
The visualization shows how a single variable 'prev' is updated and used to check BST property incrementally.
Seeing the call stack states clarifies the recursion flow and why the algorithm returns early on violations.
