Validate Binary Search Tree
Problem
https://leetcode.com/problems/validate-binary-search-tree/
Given the root of a binary tree, determine if it is a valid binary
search tree (BST).
A valid BST is defined as follows:
The left subtree of a node contains only nodes with keys strictly less than the node’s key.
The right subtree of a node contains only nodes with keys strictly greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
Example 1:

Input: root = [2,1,3]
Output: true
Example 2:

Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
Constraints:
The number of nodes in the tree is in the range
[1, 10:sup:`4`].-2:sup:`31`<= Node.val <= 2:sup:`31`- 1
Pattern
Tree, Depth-First Search, Binary Search Tree, Binary Tree
Approaches
Explanation
A binary tree is a binary search tree if every node value is within the
range defined by its ancestors. For example, the left child p.left of a
node p must be less than p.val. The grandchild p.left.right
must be between p.left.val and p.val.
We can recursively check each node to see if it is with in range. Initially,
the range is \((-\infty, \infty)\). When we go left, we update the upper
bound to be the parent node’s value. When we go right, we update the lower
bound to be the parent node’s value. If the node’s value is not within the
range, the result is False. Otherwise, the result is True.
Code
from __future__ import annotations
from collections import deque
class TreeNode:
"""Node in a binary tree."""
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
@classmethod
def from_list(cls, vals: list[int | None]) -> TreeNode | None:
if not vals:
return None
root = cls(vals[0])
queue = deque([root])
children = iter(vals[1:])
while queue:
node = queue.popleft()
for side in ("left", "right"):
val = next(children, None)
if val is not None:
child = cls(val)
setattr(node, side, child)
queue.append(child)
return root
def to_list(self) -> list:
result = []
queue = [self]
while queue:
node = queue.pop(0)
if node:
result.append(node.val)
queue.append(node.left)
queue.append(node.right)
else:
result.append(None)
while result and result[-1] is None:
result.pop()
return result
def is_valid_bst(node, left, right):
if node is None:
return True
if not (left < node.val < right):
return False
return is_valid_bst(node.left, left, node.val) and is_valid_bst(
node.right, node.val, right
)
def isValidBST(root: TreeNode | None) -> bool:
"""Return whether ``root`` is a valid binary search tree."""
return is_valid_bst(root, float("-inf"), float("inf"))
Test
>>> from validate_binary_search_tree__recursive import isValidBST, TreeNode
>>> isValidBST(TreeNode.from_list([2, 1, 3]))
True
>>> isValidBST(TreeNode.from_list([5, 1, 4, None, None, 3, 6]))
False
Complexity
\(n\) is the number of nodes in the tree, and \(d\) is the maximum depth of the tree
Measure |
Complexity |
Notes |
|---|---|---|
Time |
\(O(n)\) |
visit every node in the tree |
Auxiliary Space |
\(O(d)\) |
recursive call stack |
- class validate_binary_search_tree__recursive.TreeNode(val=0, left=None, right=None)
Bases:
objectNode in a binary tree.
- to_list() list
- validate_binary_search_tree__recursive.is_valid_bst(node, left, right)