Validate Binary Search Tree

Mediumtreebinary-search-treedepth-first-search
Category: Trees
Companies that ask this question:
AmazonFacebookMicrosoftGoogleBloomberg

Approach

Validate Binary Search Tree

Problem Statement

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 less than the node's key
  • The right subtree of a node contains only nodes with keys greater than the node's key
  • Both the left and right subtrees must also be binary search trees

Examples

Example 1

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

Tree:
    2
   / \
  1   3

Valid BST: 1 < 2 < 3 ✓

Example 2

Input: root = [5,1,4,null,null,3,6]
Output: false

Tree:
      5
     / \
    1   4
       / \
      3   6

Invalid: Node 4 is in right subtree of 5, but 4 < 5 ✗

Example 3

Input: root = [5,4,6,null,null,3,7]
Output: false

Tree:
      5
     / \
    4   6
       / \
      3   7

Invalid: Node 3 is in right subtree of 5, but 3 < 5 ✗

Intuition

Common Mistake: Just checking left.val < node.val < right.val is NOT enough!

Example: [5,1,4,null,null,3,6] - Node 3 is in right subtree of 5 but 3 < 5.

Key Insight: Every node must satisfy a range constraint:

  • Root: can be any value (-∞, +∞)
  • Left child: must be in range (min, parent.val)
  • Right child: must be in range (parent.val, max)

We pass down valid ranges and check if each node falls within its range.

Pattern Recognition

This is a DFS with Range Validation problem:

  • Pass down min/max bounds
  • Check if current node satisfies bounds
  • Update bounds for children

Approach

DFS with Min/Max Bounds

  1. Helper Function: isValid(node, min_val, max_val)

    • Returns True if subtree is valid BST within bounds
  2. For Each Node:

    • Base case: null node is valid
    • Check if min_val < node.val < max_val
    • Validate left: isValid(left, min_val, node.val)
    • Validate right: isValid(right, node.val, max_val)
  3. Initial Call: isValid(root, -∞, +∞)

Why this works:

  • Bounds ensure ALL ancestor constraints are met
  • Left child gets upper bound from parent
  • Right child gets lower bound from parent
  • Bounds propagate down the tree

In-order Traversal (Alternative)

BST property: In-order traversal produces sorted sequence!

def inorder(node):
  if not node: return True
  if not inorder(node.left): return False
  if node.val <= prev: return False
  prev = node.val
  return inorder(node.right)

If in-order is strictly increasing → valid BST

Edge Cases

  • Empty tree (valid)
  • Single node (valid)
  • Duplicate values (invalid - must be strictly < or >)
  • Integer overflow (use long or None for infinity)
  • Negative values

Complexity Analysis

  • Time: O(n) where n = number of nodes

    • Visit each node once
    • O(1) work per node
  • Space: O(h) where h = height

    • Recursion stack
    • O(log n) for balanced tree
    • O(n) for skewed tree

Solution

java
1class TreeNode {
2    int val;
3    TreeNode left;
4    TreeNode right;
5    TreeNode() {}
6    TreeNode(int val) { this.val = val; }
7    TreeNode(int val, TreeNode left, TreeNode right) {
8        this.val = val;
9        this.left = left;
10        this.right = right;
11    }
12}
13
14class Solution {
15    public boolean isValidBST(TreeNode root) {
16        return isValid(root, null, null);
17    }
18
19    private boolean isValid(TreeNode node, Integer minVal, Integer maxVal) {
20        // Base case: null node is valid
21        if (node == null) {
22            return true;
23        }
24
25        // Check if current node violates BST property
26        if ((minVal != null && node.val <= minVal) ||
27            (maxVal != null && node.val >= maxVal)) {
28            return false;
29        }
30
31        // Validate left subtree (must be < node.val)
32        // Validate right subtree (must be > node.val)
33        return isValid(node.left, minVal, node.val) &&
34               isValid(node.right, node.val, maxVal);
35    }
36}
37
Loading visualizer...