Approach Summary
Pass valid (min, max) range to each recursive call. Left child must be < node.val, right child must be > node.val.
Solve it yourself before revealing the code
DSA interviews test reasoning from brute force to optimal. Think through the constraints first.
Solution Progression (Brute Force → Most Optimized)
Understand the architectural evolution from naive baseline to optimal complexity.
| Approach | Time | Space | Core Strategy / Trade-off |
|---|---|---|---|
| 1 Approach 1: Recursive Valid Range Bounds (Optimal) | O(n) | O(h) | Pass valid (minVal, maxVal) bounds down the recursion, tightening bounds at each branch. |
| 2 Approach 2: In-Order Traversal Monotonicity Check | O(n) | O(h) | Verify that in-order traversal yields strictly monotonically increasing node values. |
Approach 1: Recursive Valid Range Bounds (Optimal)
Pass down the allowable interval for each node. When branching left, the upper bound tightens to root.val. When branching right, the lower bound tightens to root.val. Using 64-bit integer ranges avoids false negatives on 32-bit INT_MIN and INT_MAX limits.
Approach 1: Recursive Valid Range Bounds (Optimal) Implementation
Approach 1: Recursive Valid Range Bounds (Optimal)
class Solution {
private boolean check(TreeNode n, long low, long high) {
if (n == null) return true;
if (n.val <= low || n.val >= high) return false;
return check(n.left, low, n.val) && check(n.right, n.val, high);
}
public boolean isValidBST(TreeNode root) {
return check(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
}class Solution {
public:
bool check(TreeNode* n, long low, long high) {
if (!n) return true;
if (n->val <= low || n->val >= high) return false;
return check(n->left, low, n->val) && check(n->right, n->val, high);
}
bool isValidBST(TreeNode* root) {
return check(root, LONG_MIN, LONG_MAX);
}
};class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
def check(node, low, high):
if not node: return True
if node.val <= low or node.val >= high: return False
return check(node.left, low, node.val) and check(node.right, node.val, high)
return check(root, float('-inf'), float('inf'))function isValidBST(root) {
function check(n, low, high) {
if (!n) return true;
if (n.val <= low || n.val >= high) return false;
return check(n.left, low, n.val) && check(n.right, n.val, high);
}
return check(root, -Infinity, Infinity);
} Approach 2: In-Order Traversal Monotonicity Check
An in-order traversal of a BST visits elements in sorted order. Track the value of the previously visited node in a pointer or state variable. If the current node's value is <= prev, return false.
Approach 2: In-Order Traversal Monotonicity Check Implementation
Approach 2: In-Order Traversal Monotonicity Check
class Solution {
private Long prev = null;
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
if (!isValidBST(root.left)) return false;
if (prev != null && root.val <= prev) return false;
prev = (long)root.val;
return isValidBST(root.right);
}
}class Solution {
public:
TreeNode* prev = NULL;
bool isValidBST(TreeNode* root) {
if (!root) return true;
if (!isValidBST(root->left)) return false;
if (prev && root->val <= prev->val) return false;
prev = root;
return isValidBST(root->right);
}
};class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
prev = None
def inorder(node):
nonlocal prev
if not node: return True
if not inorder(node.left): return False
if prev is not None and node.val <= prev: return False
prev = node.val
return inorder(node.right)
return inorder(root)function isValidBST(root) {
let prev = null;
function inorder(node) {
if (!node) return true;
if (!inorder(node.left)) return false;
if (prev !== null && node.val <= prev) return false;
prev = node.val;
return inorder(node.right);
}
return inorder(root);
} Edge Cases to Watch
- Nodes with INT_MIN or INT_MAX values (requires 64-bit long/float bounds to prevent false overflow)
- Subtree has node that satisfies local parent but violates root (e.g. [5, 4, 6, null, null, 3, 7]; 3 is right of 4 but less than root 5; returns false)
- Duplicate values (BST requires strict inequality < and >; duplicate returns false)
Master the Trees / DFS Pattern
Study the core invariant, step-by-step decision framework, and common interview traps for the Trees / DFS pattern.
How to Recognize This Pattern
- Validate BST property
- Range propagation
Complexity Analysis
Time Complexity
O(n)
Space Complexity
O(h)