◀ THE GRIND — TREES

Validate Binary Search Tree

MEDIUM✓ CHIP-TIMEDLC #98 — FULL STATEMENT ↗

The drill: Check whether a binary tree is a true BST — not just locally sane at each node, but consistent with every ancestor above it, all the way to the root.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A binary tree arrives, and the job is deciding whether it truly satisfies the BST property everywhere, not just between neighboring nodes.

Local sanity — left child smaller, right child bigger — isn't sufficient on its own; a node several levels down must still respect every ancestor's ordering, not merely its direct parent.

Equal values anywhere in the tree break the strict ordering the same way a misplaced value would, so the verdict is a single yes-or-no: true if the whole structure is a valid BST end to end, false the moment any node breaks the ordering inherited from above.

EX 01
root = []
true
EMPTY TREE, VACUOUSLY VALID
EX 02
root = [2, 1, 3]
true
CANONICAL VALID BST
EX 03
root = [5, 1, 4, null, null, 3, 6]
false
LOCALLY SANE, GLOBALLY BROKEN
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Checking only "left child smaller, right child bigger" at each node isn't enough — a node three levels down can violate an ancestor two levels above its own parent.

HINT 2 THE STRUCTURE

Every node actually lives inside a valid range, and that range is set by the whole chain of ancestors above it, not just its direct parent.

HINT 3 ONE STEP FROM THE ANSWER

Carry (low, high) bounds downward: going left tightens the high bound to the current value, going right tightens the low bound. A node fails the instant it falls outside its inherited range.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE SHRINKING WINDOWPATTERN · BOUNDS PROPAGATIONroot = [5, 1, 4, null, null, 3, 6]
STEP 1

Local sanity — left smaller, right bigger — isn't enough. Every node must respect the FULL chain of ancestor bounds.

STEP 1 / 6 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/validate-binary-search-tree.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        def valid(node: Optional[TreeNode], low: float, high: float) -> bool:
            if not node:
                return True
            if not (low < node.val < high):
                return False
            return valid(node.left, low, node.val) and valid(node.right, node.val, high)

        return valid(root, float("-inf"), float("inf"))
TIME O(N)SPACE O(H)PYTHON · RACE PACE · 10 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED