1. What is a Binary Search Tree?
A Binary Search Tree (BST) is a type of binary tree where:
- For every node:
- All nodes in the left subtree have values less than the node’s value.
- All nodes in the right subtree have values greater than the node’s value.
- Both the left and right subtrees must themselves also be BSTs.
Example of a valid BST:
10 / \ 5 15 / \ 12 20
Example of an invalid BST:
10 / \ 5 8 ← 8 is less than 10 but in the right subtree
2. What Does It Mean to Validate a BST?
Validation means checking whether a binary tree obeys the BST property.
A common mistake is to check only that:
node.left.val < node.val && node.right.val > node.val
But this is not enough. We must ensure that all nodes in the left and right subtrees satisfy the conditions recursively.
3. Common Mistakes
- Only comparing immediate children.
- Not checking the full valid range of values in subtrees.
- Not handling
Integer.MIN_VALUE
andInteger.MAX_VALUE
edge cases correctly.
4. Approaches to Validate a BST
Approach 1: Inorder Traversal Method
Idea: An in-order traversal of a BST yields a sorted (increasing) sequence. So, if we traverse in-order and keep track of the previous node, we can check whether the current node’s value is greater than the previous.
class TreeNode { int val; TreeNode left, right; TreeNode(int val) { this.val = val; } } public class BSTValidator { private TreeNode prev = null; public boolean isValidBST(TreeNode root) { return inorder(root); } private boolean inorder(TreeNode node) { if (node == null) return true; if (!inorder(node.left)) return false; if (prev != null && node.val <= prev.val) return false; prev = node; return inorder(node.right); } }
Time Complexity:
- O(n): Each node is visited once.
Space Complexity:
- O(h): Recursion stack, where h is the height of the tree.
Approach 2: Recursive Min-Max (Range-based)
Idea: For each node, pass down a valid range:
- All nodes in the left subtree must be
< node.val
- All nodes in the right subtree must be
> node.val
public class BSTValidator { public boolean isValidBST(TreeNode root) { return validate(root, Long.MIN_VALUE, Long.MAX_VALUE); } private boolean validate(TreeNode node, long min, long max) { if (node == null) return true; if (node.val <= min || node.val >= max) return false; return validate(node.left, min, node.val) && validate(node.right, node.val, max); } }
Why Use long
?
To handle extreme values like Integer.MIN_VALUE
and Integer.MAX_VALUE
.
Time Complexity:
- O(n): Each node is checked once.
Space Complexity:
- O(h): Recursion stack.
Approach 3: Iterative Range-based (Using Stack)
Idea: Same as min-max method, but use an explicit stack to avoid recursion.
import java.util.*; class BSTValidator { static class NodeBound { TreeNode node; long min, max; NodeBound(TreeNode node, long min, long max) { this.node = node; this.min = min; this.max = max; } } public boolean isValidBST(TreeNode root) { if (root == null) return true; Deque<NodeBound> stack = new ArrayDeque<>(); stack.push(new NodeBound(root, Long.MIN_VALUE, Long.MAX_VALUE)); while (!stack.isEmpty()) { NodeBound current = stack.pop(); TreeNode node = current.node; if (node.val <= current.min || node.val >= current.max) return false; if (node.right != null) stack.push(new NodeBound(node.right, node.val, current.max)); if (node.left != null) stack.push(new NodeBound(node.left, current.min, node.val)); } return true; } }