INVARIANT · BST · Binary Search Trees
01
00/16
01 / COVER 14 · BST
INVARIANT · 14 · BINARY SEARCH TREES
BINARY SEARCH TREES

One ordering rule, held at every node — and every problem in this step is a consequence of it.

16Problems
16Units
15Lectures
17Live walks
← → ↑ ↓  or  W A S D  navigate SPACE next   DOUBLE-CLICK to advance I index   G goto problem   P predict H hide solutions   T close video   F fullscreen
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
02 / START HERE READ THIS ONE FIRST

HOW THIS DECK WORKS

This is not a list of problems. It is 16 learning units, and every one runs the same four beats. Go in order and the problems stop feeling random.

ASSUMEDBinary Trees, decks I–III. Every walk here is a traversal you already know; what is new is that the ordering lets you skip half of it.

01 INTROWhat the concept is, and what to watch for
02 VIDEOThe lecture, full-width in theatre mode
03 DRILLS2–4 questions checking the lecture landed
04 PROBLEMSThe sheet problems that concept unlocks

Moving around

← ↑Back a slide — or A / W → ↓Forward — or D / S / Space 2×clickDouble-click the right side to advance, left to go back. A single click never moves the deck. IThe index: every problem, clickable, with your progress GJump straight to a problem by its number FFullscreen

While you study

HHide solutions — blurs code and steps so you try first PPredict mode: call the next step before the animation plays it TClose the video — Esc works too ☐ ★Mark solved, or star to revisit. Both are saved automatically.

16 PROBLEMS · 15 LINK TO A JUDGE · THE REST ARE CONCEPTS THE DRILLS COVER

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
03 / SIGNALS WHEN YOU SEE X, REACH FOR Y

READ THE STATEMENT, NAME THE WALK

Six phrasings cover every row in this step. The point is not that a BST is fast — it is that the ordering answers a question the search was going to ask, so the work becomes a walk instead of a traversal. The right-hand column is what each phrasing permits you to write.

“FIND / SEARCH / DOES IT EXIST” IN A BST

one comparison names a direction, and the other subtree is never looked at

WALK DOWN · no recursion neededO(h)
“SMALLEST ≥ X”, “LARGEST ≤ X”, “NEXT ONE AFTER X”

the answer may be a node you already walked past, so record it on the way down

CARRY A CANDIDATE · ceil / floor / successorO(h)
“Kth SMALLEST”, “VALIDATE”, “IS IT SORTED”

in-order of a BST emits sorted values, so the question is about a sorted list

IN-ORDER WITH STATE · a counter, or the previous valueO(n) worst, less if you can stop
“A PAIR SUMMING TO K”, “MERGE TWO TREES”

sorted input plus two ends is the two-pointer scan, and a tree can supply both

TWO ITERATORS · forward and reverseO(n) time, O(h) space
“INSERT”, “DELETE”, “BUILD FROM A TRAVERSAL”

the structure changes, and the ordering says where — nothing has to be searched for

RESTRUCTURE · a failed search names the slotO(h), or O(n) to build
“LARGEST SUBTREE THAT IS A BST”, “IS THIS A BST”

a node cannot be judged from itself, so facts have to travel up from both children

POST-ORDER TUPLE · min, max, size, verdictO(n)
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
04 / CONSTRAINTS BEFORE YOU WRITE A LINE

READ THE ANSWER OFF THE CONSTRAINTS

Everything in this deck is written O(h), not O(log n), and the difference is the whole risk. Type a bound and the row it lands in rings gold.

n ≤
BUDGET
WHAT THAT BUYS YOU
n ≤ 10³
O(n²)
check every subtree with a fresh validator — correct, and the reason unit 16 exists
n ≤ 10⁵
O(n)
one traversal, doing all the work on the way past. Validate, kth, recover, merge
n ≤ 10⁵
O(h) per query
the home row for this deck: search, insert, delete, ceil, floor, LCA, successor
h ≈ log n
O(log n)
what O(h) BECOMES on a balanced tree — 10⁵ nodes is 17 comparisons
h = n
O(n) per query
the same code on sorted input: a chain, and every O(h) claim above collapses

The last row is the same code on sorted input: a plain BST does not rebalance, so h becomes n and every bound above it collapses. That is what AVL and red-black trees exist to prevent, and this sheet does not cover them.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
05 / WARMUP BEFORE ANY OF IT · 1 OF 2

WHAT THE ORDERING ACTUALLY PROMISES

DRILL 01 · RECALL

A BST is not the same claim as “each node's two children are ordered”. What is the actual rule?

It quantifies over subtrees, not children. This is the single most expensive misunderstanding in the topic — it produces a validator that returns true on an invalid tree, which is LeetCode 98's whole point. A node has to beat every ancestor, not just its parent.

DRILL 02 · RECALL

Why is every complexity in this deck written O(h) rather than O(log n)?

Nothing keeps a plain BST balanced. Insert sorted data and every value goes the same way, giving a chain of height n — and every walk in this deck becomes O(n). O(h) is the honest bound; O(log n) is what it becomes on a balanced tree, which is what AVL and red-black trees exist to guarantee.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
06 / WARMUP BEFORE ANY OF IT · 2 OF 2

WHAT THE ORDERING ACTUALLY PROMISES

DRILL 01 · TRACE

In-order traversal of a BST gives you what, and why does it matter here?

Sorted. Left, node, right — and the ordering rule guarantees everything left is smaller. Nine of the sixteen problems in this deck are that one fact used differently: count to k, check it rises, find the dips, merge two of them, walk it from both ends. Recognising it is most of the work.

DRILL 02 · BUG

Searching a BST. One line makes this an O(n) traversal of a structure built to avoid exactly that. Which?

bool find(Node* root, int key){
    if(!root) return false;
    if(root->val == key) return true;
    return find(root->left, key) || find(root->right, key);
}

It never compares to choose a direction. This is correct — it finds the key — and it is the binary-tree search, which visits every node. One comparison against root->val decides the side and discards the other subtree whole. Correct code that ignores its own data structure is the hardest kind of wrong to notice.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
07 / ROADMAP WHAT YOU ARE ABOUT TO DO

THE WHOLE RUN, 16 UNITS

Sixteen units, fifteen lectures, 2h 52m. The first six are walks — search, ceil, floor, insert, delete. Unit 07 states the fact the rest of the deck runs on, and units 08–16 are that fact applied nine ways. Unit 12 has no sheet row and unit 13 has no lecture; both are explained where they appear.

UNIT 01

WHAT A BST IS

▶ 8:543 DRILLS1 PROBLEM
UNIT 02

WALK, DO NOT SEARCH

▶ 6:333 DRILLS2 PROBLEMS
UNIT 03

CEIL — CARRY A CANDIDATE

▶ 5:363 DRILLS1 PROBLEM
UNIT 04

FLOOR — THE MIRROR

▶ 5:002 DRILLS1 PROBLEM
UNIT 05

INSERT WITHOUT RESTRUCTURING

▶ 8:183 DRILLS1 PROBLEM
UNIT 06

DELETE — THE THREE CASES

▶ 15:483 DRILLS1 PROBLEM
UNIT 07

INORDER IS SORTED

▶ 8:273 DRILLS1 PROBLEM
UNIT 08

VALIDATE BY RANGE

▶ 9:393 DRILLS1 PROBLEM
UNIT 09

LCA IS THE SPLIT POINT

▶ 8:063 DRILLS1 PROBLEM
UNIT 10

BUILD FROM PREORDER

▶ 16:323 DRILLS1 PROBLEM
UNIT 11

SUCCESSOR WITHOUT A PARENT

▶ 10:473 DRILLS1 PROBLEM
BEYOND THE SHEETUNIT 12

THE CONTROLLED STACK

▶ 14:003 DRILLSNO SHEET ROW
UNIT 13

MERGE TWO SORTED WALKS

NO LECTURE2 DRILLS1 PROBLEM
UNIT 14

TWO SUM, BOTH ENDS

▶ 15:063 DRILLS1 PROBLEM
UNIT 15

RECOVER — TWO VIOLATIONS

▶ 15:563 DRILLS1 PROBLEM
UNIT 16

LARGEST BST INSIDE A TREE

▶ 17:273 DRILLS1 PROBLEM
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
08 / INDEX PRESS I FROM ANYWHERE

INDEX — ALL 16 PROBLEMS

Click any problem to jump straight to it. Solved ones turn green. Press I from anywhere to come back here. The number is the sheet's row, not your position — the deck teaches in the order that builds, so you will meet them slightly out of numerical sequence.

Concepts · 03
Practice Problems · 13
SOLVED HAS A JUDGE LINK CONCEPT — DRILLS ONLY
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
09 / INTRO UNIT 01 · WHAT A BST IS

UNIT 01 — WHAT A BST IS

One ordering rule, held over subtrees rather than over children

THE QUESTION THIS LECTURE ANSWERS

WHAT DOES ORDERING BUY YOU THAT A BINARY TREE DOES NOT HAVE?

BST propertysubtreeheight hin-order
WHAT TO WATCH FOR
  • 01THE RULE IS ABOUT EVERYTHING ON EACH SIDE, NOT THE TWO CHILDREN
  • 02HE SAYS TWICE THAT THERE IS NO EQUAL TO IN ANY CASE
  • 03READ THE TREE LEFT TO RIGHT — IT COMES OUT SORTED
  • 04EVERY BOUND IN THIS DECK IS O(h) · h IS log n ONLY IF IT IS BALANCED
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
10 / VIDEO UNIT 01 · WHAT A BST IS

L39. Introduction to Binary Search Tree

STRIVER A2Z
WHAT A BST IS
RUNTIME 8:54
AFTER THIS → 3 DRILLS · PROBLEM #01
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
11 / DRILL UNIT 01 · WHAT A BST IS · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture states the rule twice, and the second half is the part people drop. What does it say about equality?

No equality at all. The lecture is explicit that there is no presence of equal to in any case. Judges differ on duplicates — LeetCode 98 rejects them outright — so when a problem does allow them it will say so, and it will tell you which side they take. Assuming a side is how a correct-looking validator fails one hidden test.

DRILL 02 · RECALL

The rule is stated over everything on each side, not over the two children. Why does that distinction matter?

It is the difference between a correct validator and a wrong one. A node can satisfy its parent and still sit in the wrong half of an ancestor — that is exactly the tree unit 08 is built around. The lecture says everything on the left, and it means the whole subtree.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
12 / DRILL UNIT 01 · WHAT A BST IS · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRANSFER

Insert 1, 2, 3, 4, 5 into an empty BST in that order. What have you built?

A linked list. Every value is larger than the last, so every insertion goes right and the height is n. All the O(log n) claims in this deck assume a balanced tree, and a plain BST does nothing to keep itself balanced — that is what AVL and red-black trees are for, and why sorted input is the worst case rather than the best.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
13 / MECHANISM UNIT 01 · ANATOMY · CODE MIRRORED

ONE RULE, AND IT IS NOT ABOUT CHILDREN

The definition people carry is left child smaller, right child larger, and it is wrong in a way that costs an hour on LeetCode 98. The rule is over subtrees: every value in the left subtree is smaller than the node, and every value in the right subtree is larger. A node must beat every ancestor, not just its parent. Step through and watch the window each node sits in — and notice the last slide, where reading the tree left to right gives you the values in sorted order. That is the same rule said once, and it is what the next fourteen units are built on.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
14 / CONCEPT #01 · CONCEPT · EASY

Introduction to BST

EASY concept CONCEPT · NO LEETCODE · DRILLS COVER IT
SIGNAL — WHAT GIVES IT AWAY

A concept row — the definition itself, and the two ways it is misread

INTUITION

The rule is quantified over subtrees. That single word is the difference between a validator that works and one that returns true on an invalid tree, and it is why this row exists before any code does.

STEPS
  1. Left subtree: EVERY value is smaller than the node
  2. Right subtree: EVERY value is larger than the node
  3. No equality — a duplicate has no legal side unless the problem names one
  4. Both subtrees are themselves BSTs, all the way down
  5. Therefore in-order emits the values in sorted order
BRUTE
OPTIMAL
↕ SCROLL
// the property, stated the way it is actually used
//   left subtree  : every value <  node->val
//   right subtree : every value >  node->val
//   and both subtrees are themselves BSTs
//
// consequence: in-order traversal emits sorted values.
TIMEdefinition, not an algorithm
SPACEnothing is stored
TRAP

“Left child smaller, right child larger” is a DIFFERENT and weaker claim. It accepts trees that are not BSTs, and it is the reason LeetCode 98 is a Medium.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
15 / INTRO UNIT 02 · WALK, DO NOT SEARCH

UNIT 02 — WALK, DO NOT SEARCH

A search that throws away half the remaining tree at every step

THE QUESTION THIS LECTURE ANSWERS

HOW DOES ONE COMPARISON DELETE AN ENTIRE SUBTREE?

O(h)leftmostrightmostdiscard
WHAT TO WATCH FOR
  • 01THE OPPOSITE SUBTREE IS NOT REJECTED — IT IS NEVER VISITED
  • 02A BINARY TREE WOULD NEED A FULL TRAVERSAL: O(n) AGAINST O(h)
  • 03MIN AND MAX NEED NO COMPARISON, ONLY A DIRECTION
  • 04THE MINIMUM MAY STILL HAVE A RIGHT CHILD — IT IS NOT A LEAF
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
16 / VIDEO UNIT 02 · WALK, DO NOT SEARCH

L40. Search in a Binary Search Tree

STRIVER A2Z
WALK, DO NOT SEARCH
RUNTIME 6:33
AFTER THIS → 3 DRILLS · PROBLEM #02, #03
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
17 / DRILL UNIT 02 · WALK, DO NOT SEARCH · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture opens by contrasting this with a binary tree. What would a binary tree force you to do?

Any full traversal — the point is that it is O(n). Without an ordering, no comparison tells you which way to go, so you have to be prepared to look at every node. The ordering is precisely what converts that walk into a decision, and the decision is what makes it O(h).

DRILL 02 · TRACE

In the tree [8,4,12,2,6,10,14,1,3,5,7], searching for 7 — how many nodes does the walk look at, and how many does it skip?

Four looked at, seven skipped. The walk is 8 → 4 → 6 → 7. At every step the opposite subtree is discarded whole — not visited and rejected, never visited. That is the shape of the saving, and it is why the bench greys those nodes rather than hiding them.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
18 / DRILL UNIT 02 · WALK, DO NOT SEARCH · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Finding the minimum of a BST. One line is wrong. Which?

int findMin(Node* root){
    while(root->left && root->right)
        root = root->left;
    return root->val;
}

&& should be a test on the left child alone. The minimum is the leftmost node, and the leftmost node is allowed to have a right child. This loop stops as soon as either child is missing, so on a tree whose leftmost node has a right child it returns a value that is not the minimum — and returns it silently.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
19 / MECHANISM UNIT 02 · BSTSEARCH · CODE MIRRORED

EVERY COMPARISON DELETES HALF THE REMAINING TREE

The greyed nodes are the point. At each step one comparison decides a direction, and the entire subtree on the other side is gone — not searched and rejected, never looked at. Eleven nodes, four comparisons. That is O(h), and on a balanced tree h = log n. The catch is the word balanced: a BST built from already-sorted input is a linked list, and this same walk becomes O(n).

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
20 / MECHANISM UNIT 02 · BSTMINMAX · CODE MIRRORED

THE ONLY TWO QUERIES THAT COMPARE NOTHING

Minimum and maximum need no target and no comparison at all — only a direction. Go left until there is no left, and you are standing on the smallest value in the tree. The mistake worth naming: the minimum is not necessarily a leaf. It cannot have a left child, but it may well have a right one, and code that tests isLeaf instead of !node->left is wrong on exactly that shape.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
21 / PROBLEM #02 · WALK · EASY

Search in a Binary Search Tree

EASY walk ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Find the node with this value” — and the tree is a BST

INTUITION

One comparison per level names a direction, and the subtree on the other side is discarded whole. No recursion is needed: the walk never has to come back up, because it never has to reconsider.

STEPS
  1. While the node exists and does not hold the key
  2. Key smaller: move to the left child
  3. Key larger: move to the right child
  4. Return the node — it is null exactly when the key was absent
BRUTEO(n) as a binary tree
OPTIMALO(h)
↕ SCROLL
Node* searchBST(Node* root, int val) {
    while (root && root->val != val)
        root = val < root->val ? root->left : root->right;
    return root;
}
TIMEO(h)one comparison per level
SPACEO(1)iterative, so no stack
TRAP

Writing it as a binary-tree search — recursing into both subtrees — is CORRECT and O(n). It passes, and it throws away the only reason the structure exists.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
22 / PROBLEM #03 · WALK · EASY

Find Min/Max in BST

EASY walk ▶ SOLVE ON GEEKSFORGEEKS
SIGNAL — WHAT GIVES IT AWAY

“Smallest” or “largest” value in a BST, with no key given

INTUITION

These are the only two queries here that compare nothing at all. The smallest value is the one with no smaller value to its left, so walk left until there is no left.

STEPS
  1. Minimum: follow left children until one is null
  2. Maximum: follow right children until one is null
  3. Return that node's value
  4. Neither ever compares against a target
BRUTEO(n) scanning every node
OPTIMALO(h)
↕ SCROLL
int findMin(Node* root) {
    while (root->left) root = root->left;
    return root->val;
}
int findMax(Node* root) {
    while (root->right) root = root->right;
    return root->val;
}
TIMEO(h)one edge per level
SPACEO(1)iterative
TRAP

The minimum is NOT necessarily a leaf. It cannot have a left child; it can have a right one. Looping while BOTH children exist stops early and returns the wrong value.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
23 / INTRO UNIT 03 · CEIL — CARRY A CANDIDATE

UNIT 03 — CEIL — CARRY A CANDIDATE

The answer may be a node the walk already passed

THE QUESTION THIS LECTURE ANSWERS

WHAT DO YOU RETURN WHEN THE KEY IS NOT IN THE TREE AT ALL?

ceilcandidateabsent key
WHAT TO WATCH FOR
  • 01CEIL IS THE SMALLEST VALUE ≥ THE KEY, AND THE KEY MAY BE ABSENT
  • 02A QUALIFYING NODE IS RECORDED, NOT RETURNED
  • 03AFTER RECORDING, GO LEFT — YOU WANT SOMETHING TIGHTER
  • 04WHEN THE WALK RUNS OUT, THE ANSWER IS THE LAST THING RECORDED
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
24 / VIDEO UNIT 03 · CEIL — CARRY A CANDIDATE

L41. Ceil in a Binary Search Tree

STRIVER A2Z
CEIL — CARRY A CANDIDATE
RUNTIME 5:36
AFTER THIS → 3 DRILLS · PROBLEM #04
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
25 / DRILL UNIT 03 · CEIL — CARRY A CANDIDATE · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

Ceil of a key is the smallest value greater than or equal to it. Why can the walk not simply return where it stops?

The key need not be in the tree. Ceil is asked precisely when it is not, so the walk falls off the bottom and there is nothing to return there. The answer is a node the walk passed several steps earlier — which is why the candidate has to be recorded on the way down rather than recovered at the end.

DRILL 02 · TRACE

Tree [8,4,12,2,6,10,14,1,3,5,7], ceil of 9. Which nodes does the walk stand on, and what is the answer?

8 → 12 → 10, and the answer is 10. 8 is too small so it cannot qualify; 12 qualifies and is recorded, then the walk goes left hunting something tighter; 10 qualifies and replaces it. The walk then runs out of tree, and the answer is the last thing recorded — not where it stopped.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
26 / DRILL UNIT 03 · CEIL — CARRY A CANDIDATE · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Ceil, with the candidate carried. One line is wrong. Which?

int findCeil(Node* root, int key){
    int ceil = -1;
    while(root){
        if(root->val == key) return root->val;
        if(root->val > key){ ceil = root->val; root = root->right; }
        else root = root->right;
    }
    return ceil;
}

Recording then going right is the wrong direction. A qualifying node means the answer is this node or something smaller, and smaller is to the left. Going right hunts for something larger, so the very first qualifying node is kept and the walk returns an answer that is too big — plausible, and wrong.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
27 / MECHANISM UNIT 03 · BSTCEIL · CODE MIRRORED

THE ANSWER MAY BE A NODE YOU ALREADY WALKED PAST

Ceil is the smallest value ≥ the key, and the key need not be in the tree at all. So the walk cannot just fall off the bottom and report failure: every time it stands on a node that would qualify, it records it and keeps going left, looking for something tighter. When the tree runs out, the answer is the last thing recorded. Watch the candidate panel rather than the node you are standing on — that is where the answer lives, and it is the same trick successor uses in unit 11.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
28 / PROBLEM #04 · CANDIDATE · EASY

Floor and Ceil in a BST

EASY candidate ▶ SOLVE ON GEEKSFORGEEKS
SIGNAL — WHAT GIVES IT AWAY

“Smallest value greater than or equal to X” — X need not be present

INTUITION

Because the key may be absent, the walk can fall off the bottom with nothing to return. So every time you stand on a node that would qualify, record it and keep going left looking for something tighter. The last thing recorded is the answer.

STEPS
  1. ceil = -1 to start — the honest answer when nothing qualifies
  2. At each node: if it equals the key, that IS the ceil
  3. If it is larger, record it as the candidate and go LEFT
  4. If it is smaller, it cannot qualify — go RIGHT
  5. When the walk runs out, return the candidate
BRUTEO(n) collecting and scanning
OPTIMALO(h)
↕ SCROLL
int findCeil(Node* root, int key) {
    int ceil = -1;
    while (root) {
        if (root->val == key) return root->val;
        if (root->val > key) { ceil = root->val; root = root->left; }
        else root = root->right;
    }
    return ceil;
}
TIMEO(h)one comparison per level
SPACEO(1)one integer of state
TRAP

Recording a candidate and then walking RIGHT keeps the first qualifier and returns a value that is too large. After recording, you always hunt in the direction of tighter answers.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
29 / INTRO UNIT 04 · FLOOR — THE MIRROR

UNIT 04 — FLOOR — THE MIRROR

The same walk with both the comparison and the direction reversed

THE QUESTION THIS LECTURE ANSWERS

IF FLOOR IS CEIL MIRRORED, WHY IS IT ITS OWN LECTURE?

floormirrorpredecessor
WHAT TO WATCH FOR
  • 01FLOOR IS THE GREATEST VALUE ≤ THE KEY
  • 02THE OR EQUAL TO IS LOAD-BEARING — A PRESENT KEY IS ITS OWN FLOOR
  • 03QUALIFY ON val < key, RECORD, THEN GO RIGHT
  • 04FLIPPING ONLY ONE OF THE TWO IS THE BUG THIS UNIT EXISTS FOR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
30 / VIDEO UNIT 04 · FLOOR — THE MIRROR

L42. Floor in a Binary Search Tree

STRIVER A2Z
FLOOR — THE MIRROR
RUNTIME 5:00
AFTER THIS → 2 DRILLS · PROBLEM #05
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
31 / DRILL UNIT 04 · FLOOR — THE MIRROR

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

How does the lecture define floor?

Greatest value ≤ the key — and the or equal to is load-bearing. If the key is present, the key is its own floor and its own ceil. Dropping equality gives you strict predecessor instead, which is a different problem and a different answer on exactly the inputs a judge tests.

DRILL 02 · TRANSFER

You have working ceil code. What is the smallest correct edit that turns it into floor?

Both, or neither. Floor qualifies on val < key and then hunts larger, so it records and goes right. Flipping one of the two is the bug that makes this its own unit rather than a footnote: it returns a plausible number on many trees and the wrong one on the rest.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
32 / MECHANISM UNIT 04 · BSTFLOOR · CODE MIRRORED

THE SAME WALK WITH BOTH SIGNS FLIPPED

Floor is the largest value ≤ the key, and the code is ceil with the comparison and the direction both reversed: qualify on val < key, record, then go right looking for something larger. Flipping only one of the two is the bug that produces a plausible number on most inputs and the wrong one on the rest, which is why this gets its own unit rather than a footnote.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
33 / PROBLEM #05 · CANDIDATE · EASY

Floor in a Binary Search Tree

EASY candidate ▶ SOLVE ON GEEKSFORGEEKS
SIGNAL — WHAT GIVES IT AWAY

“Largest value less than or equal to X” — the mirror of ceil

INTUITION

Identical walk, with both the comparison and the direction reversed. Qualify on strictly smaller, record, then go right hunting something larger. Flipping only one of the two is the bug that makes this its own row rather than a footnote.

STEPS
  1. floor = -1 to start
  2. If the node equals the key, that IS the floor
  3. If it is smaller, record it and go RIGHT
  4. If it is larger, it cannot qualify — go LEFT
  5. Return the last candidate recorded
BRUTEO(n) collecting and scanning
OPTIMALO(h)
↕ SCROLL
int findFloor(Node* root, int key) {
    int floor = -1;
    while (root) {
        if (root->val == key) return root->val;
        if (root->val < key) { floor = root->val; root = root->right; }
        else root = root->left;
    }
    return floor;
}
TIMEO(h)one comparison per level
SPACEO(1)one integer of state
TRAP

Dropping the “or equal to” turns floor into strict predecessor. When the key IS in the tree the two answers differ, and that is exactly what a judge tests.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
34 / INTRO UNIT 05 · INSERT WITHOUT RESTRUCTURING

UNIT 05 — INSERT WITHOUT RESTRUCTURING

A failed search ends exactly where the new node belongs

THE QUESTION THIS LECTURE ANSWERS

WHY DOES INSERTING NEVER HAVE TO MOVE AN EXISTING NODE?

insertnull slotshape
WHAT TO WATCH FOR
  • 01THE WALK IS THE SEARCH FOR THE VALUE YOU ARE INSERTING
  • 02THE NULL IT ENDS ON IS THE ONLY LEGAL SLOT
  • 03NOTHING EXISTING MOVES, AND NO SUBTREE IS REBUILT
  • 04THE HEIGHT IS NOT PRESERVED — SORTED INPUT BUILDS A CHAIN
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
35 / VIDEO UNIT 05 · INSERT WITHOUT RESTRUCTURING

L43. Insert a given Node in Binary Search Tree

STRIVER A2Z
INSERT WITHOUT RESTRUCTURING
RUNTIME 8:18
AFTER THIS → 3 DRILLS · PROBLEM #06
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
36 / DRILL UNIT 05 · INSERT WITHOUT RESTRUCTURING · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture is emphatic that insertion must preserve one thing. What?

The BST property, over the subtrees. Note what is not preserved: the height. A plain BST does not rebalance on insert, so a run of increasing values grows a chain. Keeping the property is the requirement; keeping the height is what balanced trees add on top.

DRILL 02 · TRANSFER

Why does insertion never have to move an existing node?

The failed search IS the insertion point. The walk only ever moved in directions the ordering permitted, so the null it stops at is the one place the value can sit without breaking anything. That is why insert is a search with one extra line, and why no subtree is ever rebuilt.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
37 / DRILL UNIT 05 · INSERT WITHOUT RESTRUCTURING · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Recursive insert. One line makes the new node vanish. Which?

void insert(Node* root, int val){
    if(root == nullptr){ root = new Node(val); return; }
    if(val < root->val) insert(root->left, val);
    else insert(root->right, val);
}

The pointer is passed by value. root = new Node(val) rewrites a local copy of the pointer; the parent's left or right still holds null when the call returns. Nothing crashes and nothing is reported — the value is simply not in the tree. The fix is to return the node and assign it: root->left = insert(root->left, val).

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
38 / MECHANISM UNIT 05 · BSTINSERT · CODE MIRRORED

A FAILED SEARCH ENDS EXACTLY WHERE THE NODE BELONGS

Insert is not a separate algorithm. Run the search for the value you are inserting; because the value is not there, the walk ends at a null — and that null is precisely the slot where the value has to go, because the walk only ever went in directions the ordering permitted. So nothing existing moves, and no subtree is rebuilt. That is also why insertion order decides the shape: insert sorted data and every step goes the same way.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
39 / PROBLEM #06 · RESTRUCTURE · MED

Insert a given node in BST

MED restructure ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Insert this value and keep it a BST”

INTUITION

Run the search for the value you are inserting. It is not there, so the walk ends at a null — and that null is the only slot the value can occupy, because the walk only ever moved in directions the ordering permitted. Nothing existing moves.

STEPS
  1. If the tree is empty, the new node is the root
  2. Walk down comparing, exactly as a search would
  3. When the child on the chosen side is null, attach there
  4. Return the root, unchanged in identity
BRUTEO(n) rebuilding the tree
OPTIMALO(h)
↕ SCROLL
Node* insertIntoBST(Node* root, int val) {
    if (!root) return new Node(val);
    Node* cur = root;
    while (true) {
        if (val < cur->val) {
            if (!cur->left) { cur->left = new Node(val); break; }
            cur = cur->left;
        } else {
            if (!cur->right) { cur->right = new Node(val); break; }
            cur = cur->right;
        }
    }
    return root;
}
TIMEO(h)the search walk, plus one link
SPACEO(1)iterative
TRAP

Passing the node pointer by value and assigning root = new Node(v) writes to a local copy. Nothing crashes; the value is simply not in the tree afterwards.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
40 / INTRO UNIT 06 · DELETE — THE THREE CASES

UNIT 06 — DELETE — THE THREE CASES

Three cases, and only the third is a real problem

THE QUESTION THIS LECTURE ANSWERS

WHAT REPLACES A NODE THAT HAS TWO CHILDREN?

successorsplicetwo-child case
WHAT TO WATCH FOR
  • 01A LEAF IS UNHOOKED; ONE CHILD IS PROMOTED — BOTH ONE LINE
  • 02TWO CHILDREN: COPY THE IN-ORDER SUCCESSOR'S VALUE IN
  • 03THE SUCCESSOR IS THE LEFTMOST OF THE RIGHT SUBTREE
  • 04IT HAS AT MOST ONE CHILD, SO THE HARD CASE BECOMES AN EASY ONE
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
41 / VIDEO UNIT 06 · DELETE — THE THREE CASES

L44. Delete a Node in Binary Search Tree

STRIVER A2Z
DELETE — THE THREE CASES
RUNTIME 15:48
AFTER THIS → 3 DRILLS · PROBLEM #07
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
42 / DRILL UNIT 06 · DELETE — THE THREE CASES · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

Deleting a node with two children. Which value replaces it?

The in-order successor — or the predecessor, symmetrically. It is the only value larger than everything in the left subtree and smaller than everything else in the right, so it is the only value that fits the hole. Promoting a child breaks the order the moment that child has children of its own.

DRILL 02 · TRANSFER

Why is the two-child case not actually the hardest thing here?

It reduces to a case you have already solved. The successor is the leftmost node of the right subtree, so by construction it has no left child — at most one child total. Copy its value up, then delete it, and that deletion is the easy case. The recursion bottoms out immediately.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
43 / DRILL UNIT 06 · DELETE — THE THREE CASES · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

The two-child branch of delete. One line is wrong. Which?

else {
    Node* s = root->right;
    while(s->right) s = s->right;
    root->val = s->val;
    root->right = deleteNode(root->right, s->val);
}

It finds the maximum of the right subtree, not the minimum. Walking right lands on the largest value there, which is larger than other values in that same subtree — so promoting it puts a value above things that must exceed it. Walking s->left gives the successor. Predecessor works too, but then you must take the largest of the left subtree, not the right.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
44 / MECHANISM UNIT 06 · BSTDELETE · CODE MIRRORED

TWO OF THE THREE CASES ARE NOT DELETION AT ALL

A leaf is unhooked. A node with one child is replaced by that child — both are one line. The only real case is two children, and the trick is that you do not move the node: you copy the in-order successor's value into it and then delete the successor instead. The successor is the smallest value in the right subtree, so it is the unique value that is larger than everything on the left and smaller than everything else on the right. And it has at most one child by construction — so the hard case reduces to an easy one.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
45 / PROBLEM #07 · RESTRUCTURE · MED

Delete a node in BST

MED restructure ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Remove this value and keep it a BST”

INTUITION

Two of the three cases are not really deletion. A leaf is unhooked; a node with one child is replaced by that child. The only real case is two children — and it is solved by not moving the node at all: copy the in-order successor's value in, then delete the successor.

STEPS
  1. Walk down to find the node, recursing into the correct side
  2. No left child: return the right child (covers leaf too)
  3. No right child: return the left child
  4. Two children: find the leftmost node of the right subtree
  5. Copy its value up, then delete that value from the right subtree
BRUTEO(n) rebuilding from the values
OPTIMALO(h)
↕ SCROLL
Node* deleteNode(Node* root, int key) {
    if (!root) return nullptr;
    if (key < root->val) root->left = deleteNode(root->left, key);
    else if (key > root->val) root->right = deleteNode(root->right, key);
    else {
        if (!root->left) return root->right;
        if (!root->right) return root->left;
        Node* s = root->right;
        while (s->left) s = s->left;
        root->val = s->val;
        root->right = deleteNode(root->right, s->val);
    }
    return root;
}
TIMEO(h)one walk down, then one more
SPACEO(h)the recursion stack
TRAP

Taking the largest of the RIGHT subtree instead of the smallest promotes a value above nodes that must exceed it. Successor is leftmost-of-right; predecessor is rightmost-of-LEFT.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
46 / INTRO UNIT 07 · INORDER IS SORTED

UNIT 07 — INORDER IS SORTED

In-order is sorted, so the kth node visited is the kth smallest

THE QUESTION THIS LECTURE ANSWERS

HOW DO YOU GET THE Kth SMALLEST WITHOUT SORTING ANYTHING?

kth smallestcounterearly exit
WHAT TO WATCH FOR
  • 01THE NAIVE FORM COLLECTS EVERYTHING AND SORTS AN ALREADY-SORTED WALK
  • 02IN-ORDER + A COUNTER NEEDS NO CONTAINER AT ALL
  • 03THE TRAVERSAL STOPS THE MOMENT THE COUNTER REACHES k
  • 04THE COUNTER MUST BE BY REFERENCE, OR IT RESETS PER SUBTREE
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
47 / VIDEO UNIT 07 · INORDER IS SORTED

L45. K-th Smallest/Largest Element in BST

STRIVER A2Z
INORDER IS SORTED
RUNTIME 8:27
AFTER THIS → 3 DRILLS · PROBLEM #08
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
48 / DRILL UNIT 07 · INORDER IS SORTED · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture opens with the naive solution before improving it. What is it?

Traverse into a container, sort, index. Naming it matters because of what it wastes: an in-order walk is already sorted, so the sort is pure loss and the container is O(n) memory for a question that needs a counter. The improvement is not a different algorithm, it is noticing what you already had.

DRILL 02 · TRACE

Tree [8,4,12,2,6,10,14,1,3]. The 4th smallest is 4. How many of the 9 nodes does a counting in-order walk visit?

Four. In-order visits 1, 2, 3, 4 and stops — the remaining five nodes are never touched. That early exit is the entire optimisation, and it is what a sort-the-array solution throws away. Watch the bench: over half the tree stays untouched.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
49 / DRILL UNIT 07 · INORDER IS SORTED · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Counting in-order for the kth smallest. One line breaks the count. Which?

int kth(Node* n, int k){
    int cnt = 0;
    if(!n) return -1;
    kth(n->left, k);
    if(++cnt == k) return n->val;
    return kth(n->right, k);
}

The counter is per-call. Declaring cnt inside the function resets it in every subtree, so ++cnt is always 1 and the test only ever fires for k = 1. The counter has to outlive the recursion — pass it by reference, or make it a member. The discarded left result is a second real bug in this listing, which is why the shipped version returns through a reference parameter instead.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
50 / MECHANISM UNIT 07 · BSTKTH · CODE MIRRORED

STOP THE WALK, DO NOT SORT THE TREE

The whole problem is one observation: in-order traversal of a BST emits values in sorted order, so the k-th node visited is the k-th smallest. Nothing is sorted, nothing is collected into an array, and the traversal stops the moment the counter hits k — watch how many nodes are never visited at all. The counter has to be passed by reference; making it a local is the classic bug, and it silently restarts the count in every subtree.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
51 / PROBLEM #08 · INORDER · MED

Kth Smallest and Largest element in BST

MED inorder ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“kth smallest” or “kth largest” in a BST

INTUITION

In-order emits sorted values, so the kth node visited is the kth smallest — no container, no sort, and the walk stops the moment the counter reaches k. For kth LARGEST, run the mirror: right, node, left.

STEPS
  1. Walk in-order: left subtree, node, right subtree
  2. Increment a counter as each node is visited
  3. When the counter equals k, that node is the answer
  4. Stop — the remaining nodes are never visited
  5. For kth largest, reverse the walk to right-node-left
BRUTEO(n log n) collect and sort
OPTIMALO(k)
↕ SCROLL
void kth(Node* n, int k, int& cnt, int& ans) {
    if (!n || ans != -1) return;
    kth(n->left, k, cnt, ans);
    if (++cnt == k) { ans = n->val; return; }
    kth(n->right, k, cnt, ans);
}
TIMEO(k)stops at the kth visit
SPACEO(h)the recursion stack
TRAP

A counter declared inside the recursion resets in every subtree, so the test only fires for k = 1. It must be a reference parameter or a member.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
52 / INTRO UNIT 08 · VALIDATE BY RANGE

UNIT 08 — VALIDATE BY RANGE

Every node carries a window, and a parent alone cannot supply it

THE QUESTION THIS LECTURE ANSWERS

WHY DOES COMPARING EACH NODE TO ITS CHILDREN NOT WORK?

rangewindowstrictly increasing
WHAT TO WATCH FOR
  • 01THE COUNTEREXAMPLE PASSES A PARENT-ONLY CHECK AND IS NOT A BST
  • 02EACH NODE NARROWS THE RANGE ITS SUBTREES MAY USE
  • 03THE ALTERNATIVE IS AN IN-ORDER THAT MUST STRICTLY INCREASE
  • 04INT_MIN AS A BOUND REJECTS A TREE THAT CONTAINS IT
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
53 / VIDEO UNIT 08 · VALIDATE BY RANGE

L46. Check if a tree is a BST or BT

STRIVER A2Z
VALIDATE BY RANGE
RUNTIME 9:39
AFTER THIS → 3 DRILLS · PROBLEM #09
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
54 / DRILL UNIT 08 · VALIDATE BY RANGE · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

Why is comparing each node against its two children not a correct BST check?

The rule reaches further than one level. A 6 placed under 12 is a legal left child, and illegal as a descendant of 8, because everything in 8's right subtree must exceed 8. A parent-only check returns true on that tree. Carrying a window down is what catches it — this unit's bench is built on exactly that tree.

DRILL 02 · TRANSFER

An alternative correct check is an in-order walk. What exactly must it verify?

Strictly increasing. In-order of a BST is sorted, so any value not greater than its predecessor proves a violation. Strictly matters: allowing equality accepts duplicates, which LeetCode 98 rejects. This is the same fact unit 07 counted on and unit 15 will hunt dips in.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
55 / DRILL UNIT 08 · VALIDATE BY RANGE · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Range-based validation. One line fails on a legitimate input. Which?

bool valid(Node* n, int lo, int hi){
    if(!n) return true;
    if(n->val <= lo || n->val >= hi) return false;
    return valid(n->left, lo, n->val)
        && valid(n->right, n->val, hi);
}

The sentinel collides with a real value. Called as valid(root, INT_MIN, INT_MAX), a node legitimately holding INT_MIN fails val <= lo and a valid tree is reported invalid. Use long bounds, or pass nullable pointers and skip the comparison when a bound is absent. LeetCode 98 tests this exact case.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
56 / MECHANISM UNIT 08 · BSTVALIDATE · CODE MIRRORED

THE TREE THAT PASSES A PARENT-ONLY CHECK

This tree is drawn to break the wrong solution. Every node satisfies its own parent, so code that compares a node against node->left and node->right returns true — and the tree is not a BST. The 6 under 12 is fine as a left child and illegal as a descendant of 8, because everything in 8's right subtree must exceed 8. The fix is to carry a window down: each node narrows the range its subtrees may use. Use long for the bounds, or a tree containing INT_MIN breaks it.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
57 / PROBLEM #09 · INORDER · MED

Check if a tree is a BST or not

MED inorder ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Is this a valid BST?” — the question the definition is really about

INTUITION

A node must satisfy every ancestor, not just its parent. So carry a window down: each node narrows the range its subtrees may use. The alternative is an in-order walk that must strictly increase, which is the same fact from the other side.

STEPS
  1. Start at the root with an unbounded window
  2. A node must lie strictly inside its window, or the tree fails
  3. Recurse left with the upper bound tightened to this node's value
  4. Recurse right with the lower bound raised to this node's value
  5. Both sides must pass
BRUTEO(n²) re-scanning subtrees
OPTIMALO(n)
↕ SCROLL
bool valid(Node* n, long lo, long hi) {
    if (!n) return true;
    if (n->val <= lo || n->val >= hi) return false;
    return valid(n->left, lo, n->val)
        && valid(n->right, n->val, hi);
}
bool isValidBST(Node* root) {
    return valid(root, LONG_MIN, LONG_MAX);
}
TIMEO(n)each node visited once
SPACEO(h)the recursion stack
TRAP

INT_MIN and INT_MAX as starting bounds reject a valid tree that contains those values. Use long, or nullable bounds.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
58 / INTRO UNIT 09 · LCA IS THE SPLIT POINT

UNIT 09 — LCA IS THE SPLIT POINT

The first node where the two targets disagree

THE QUESTION THIS LECTURE ANSWERS

WHY DOES LCA IN A BST NEED NO RECURSION AT ALL?

LCAsplit pointroot path
WHAT TO WATCH FOR
  • 01BOTH SMALLER, GO LEFT · BOTH LARGER, GO RIGHT
  • 02THE FIRST DISAGREEMENT IS THE ANSWER, AND YOU STOP THERE
  • 03A GENERAL TREE MUST SEARCH BOTH SUBTREES AND RETURN UPWARD
  • 04IT IS THE FIRST INTERSECTION OF THE TWO ROOT-PATHS
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
59 / VIDEO UNIT 09 · LCA IS THE SPLIT POINT

L47. LCA in Binary Search Tree

STRIVER A2Z
LCA IS THE SPLIT POINT
RUNTIME 8:06
AFTER THIS → 3 DRILLS · PROBLEM #10
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
60 / DRILL UNIT 09 · LCA IS THE SPLIT POINT · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture defines LCA by drawing both root-paths. What is the LCA on that picture?

The first intersection of the two paths. That framing is what makes the BST shortcut obvious: the paths run together while both targets lie on the same side, and split at the first node where they disagree. So the split point is the intersection, and you can stop there.

DRILL 02 · TRANSFER

In a general binary tree, LCA recurses into both subtrees and returns results upward. Why is none of that needed here?

The ordering answers what the search was for. In a general tree you must look in both subtrees because nothing tells you where a value is. Here one comparison does, so it is a single walk down with no return path and no bookkeeping — O(h) time and O(1) space iteratively.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
61 / DRILL UNIT 09 · LCA IS THE SPLIT POINT · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRACE

Tree [8,4,12,2,6,10,14,1,3,5,7]. LCA of 1 and 7?

4. At 8 both 1 and 7 are smaller, so both go left. At 4, 1 is smaller and 7 is larger — they disagree, and 4 is the answer. Note it is not the root: the root is the first place they could split, not the first place they do.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
62 / MECHANISM UNIT 09 · BSTLCA · CODE MIRRORED

THE FIRST DISAGREEMENT IS THE ANSWER

In a general binary tree, LCA means recursing into both subtrees and returning results back up. In a BST it is a single walk with no recursion at all: while both targets are smaller than the node, go left; while both are larger, go right. The first node where they disagree — one goes left, one goes right, or one IS the node — has both beneath it and nothing lower does. You stop the instant it happens.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
63 / PROBLEM #10 · WALK · MED

LCA in BST

MED walk ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Lowest common ancestor” — and the tree is a BST

INTUITION

Walk from the root while both targets lie on the same side. The first node where they disagree — one goes left, one goes right, or one IS the node — has both beneath it, and nothing lower does. You stop the instant it happens.

STEPS
  1. Both targets smaller than the node: go left
  2. Both targets larger: go right
  3. Otherwise they have split, and this node is the LCA
  4. No recursion and no returning results upward
BRUTEO(n) as a general binary tree
OPTIMALO(h)
↕ SCROLL
Node* lowestCommonAncestor(Node* root, Node* p, Node* q) {
    while (root) {
        if (p->val < root->val && q->val < root->val) root = root->left;
        else if (p->val > root->val && q->val > root->val) root = root->right;
        else return root;
    }
    return nullptr;
}
TIMEO(h)one comparison per level
SPACEO(1)iterative
TRAP

The LCA is not the root just because the targets are far apart, and it is not necessarily either target's parent. It is the first split, wherever that falls.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
64 / INTRO UNIT 10 · BUILD FROM PREORDER

UNIT 10 — BUILD FROM PREORDER

The bound is the information the array does not give you

THE QUESTION THIS LECTURE ANSWERS

PREORDER ALONE IS AMBIGUOUS FOR A BINARY TREE — WHY NOT FOR A BST?

preorderupper boundone pass
WHAT TO WATCH FOR
  • 01THE NAIVE BUILD INSERTS FROM THE ROOT EACH TIME: O(n²)
  • 02EACH CALL CARRIES AN UPPER BOUND AND STOPS WHEN A VALUE EXCEEDS IT
  • 03THAT RETURN IS WHAT MARKS WHERE A SUBTREE ENDS
  • 04THE INDEX IS SHARED — A REJECTED VALUE IS NOT CONSUMED
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
65 / VIDEO UNIT 10 · BUILD FROM PREORDER

L48. Construct a BST from a preorder traversal

STRIVER A2Z
BUILD FROM PREORDER
RUNTIME 16:32
AFTER THIS → 3 DRILLS · PROBLEM #11
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
66 / DRILL UNIT 10 · BUILD FROM PREORDER · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

Before the one-pass method, the lecture names the naive construction. What is it?

Insert each value from the root in turn. That is O(n²) in the worst case — and the worst case is a sorted preorder, which is a chain. Worth naming because it is correct and will pass small tests, so the reason to replace it is the bound, not the behaviour.

DRILL 02 · TRANSFER

Preorder alone determines a binary search tree but not a general binary tree. What supplies the missing information?

The ordering. For a general tree you need two traversals because preorder cannot say where the left subtree ends. In a BST it can: the left subtree is exactly the prefix of values below the node, and the first value above it starts the right subtree. That boundary is what the upper bound detects in one pass.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
67 / DRILL UNIT 10 · BUILD FROM PREORDER · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRACE

Preorder [8,5,1,7,10,12], building 8's left subtree with bound 8. The scan reaches 10. What happens?

It returns, leaving 10 unconsumed. That is the whole mechanism: the recursion does not look for the subtree boundary, it walks into it and is turned back by the bound. Because the index is shared and 10 was never consumed, the caller's right branch picks it up next. Skipping it would lose a node.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
68 / MECHANISM UNIT 10 · BSTPREORDER · CODE MIRRORED

THE BOUND CARRIES THE INFORMATION THE ARRAY LEFT OUT

A preorder list alone is ambiguous for a general binary tree, and unambiguous for a BST — the ordering supplies the missing structure. The naive build is O(n²) (insert each value from the root) and the sort-and-recurse trick is O(n log n). This is one pass: each call carries an upper bound, takes the next value only if it is under that bound, and returns the moment it is not. That return is what tells the scan where a subtree ends, which is the only thing the array does not say out loud.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
69 / PROBLEM #11 · BOUNDS · MED

Construct a BST from a preorder traversal

MED bounds ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Build the BST whose preorder is this array”

INTUITION

Preorder alone is ambiguous for a general binary tree and unambiguous for a BST, because the ordering supplies the missing structure. One pass: each call carries an upper bound and returns the moment the next value exceeds it — and that return is what marks where a subtree ends.

STEPS
  1. Keep a shared index into the preorder array
  2. Each call takes the next value only if it is under its bound
  3. Build the left subtree with the bound tightened to this node
  4. Build the right subtree with the bound inherited from the caller
  5. A rejected value is NOT consumed, so the caller picks it up
BRUTEO(n²) inserting each from the root
OPTIMALO(n)
↕ SCROLL
Node* build(vector<int>& pre, int& i, int bound) {
    if (i == pre.size() || pre[i] > bound) return nullptr;
    Node* n = new Node(pre[i++]);
    n->left  = build(pre, i, n->val);
    n->right = build(pre, i, bound);
    return n;
}
Node* bstFromPreorder(vector<int>& pre) {
    int i = 0;
    return build(pre, i, INT_MAX);
}
TIMEO(n)every value taken once
SPACEO(h)the recursion stack
TRAP

Advancing the index past a rejected value loses a node. The index must only move when a value is actually taken.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
70 / INTRO UNIT 11 · SUCCESSOR WITHOUT A PARENT

UNIT 11 — SUCCESSOR WITHOUT A PARENT

The candidate trick again, on the in-order order

THE QUESTION THIS LECTURE ANSWERS

WHERE IS THE SUCCESSOR OF A NODE WITH NO RIGHT CHILD?

successorpredecessorcandidate
WHAT TO WATCH FOR
  • 01IN-ORDER IS LEFT, NODE, RIGHT — THE SUCCESSOR IS THE NEXT LARGER
  • 02WITH A RIGHT CHILD: THE LEFTMOST OF THAT SUBTREE
  • 03WITHOUT ONE: THE LAST ANCESTOR THE WALK TURNED LEFT AT
  • 04SUCCESSOR IS STRICTLY GREATER — CEIL IS THE ONE THAT ALLOWS EQUAL
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
71 / VIDEO UNIT 11 · SUCCESSOR WITHOUT A PARENT

L49. Inorder Successor/Predecessor in BST

STRIVER A2Z
SUCCESSOR WITHOUT A PARENT
RUNTIME 10:47
AFTER THIS → 3 DRILLS · PROBLEM #12
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
72 / DRILL UNIT 11 · SUCCESSOR WITHOUT A PARENT · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture defines the successor through one traversal in particular. Which, and in what order?

In-order: left, node, right. The successor is defined as the next value in that sequence, and since in-order of a BST is sorted, the successor is just the next larger value. Naming the traversal is what turns a tree question into a sorted-list question.

DRILL 02 · TRANSFER

A node has no right child. Where is its successor?

The last left turn on the way down. With no right child the answer is not below the node at all — it is above it. Rather than special-casing the two shapes, walk from the root once and record a candidate whenever you turn left; that candidate is the answer. It is the ceil trick from unit 03, and it needs no parent pointers.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
73 / DRILL UNIT 11 · SUCCESSOR WITHOUT A PARENT · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · BUG

Successor by carried candidate. One line is wrong. Which?

Node* successor(Node* root, int key){
    Node* best = nullptr;
    while(root){
        if(root->val >= key){ best = root; root = root->left; }
        else root = root->right;
    }
    return best;
}

>= lets the key be its own successor. With the key present in the tree, the walk records the key itself and returns it — so successor(8) comes back as 8. Successor is strictly greater; ceil is the one that allows equality. One character, and it only shows up when the key is actually in the tree.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
74 / MECHANISM UNIT 11 · BSTSUCC · CODE MIRRORED

THE CANDIDATE TRICK, APPLIED TO THE IN-ORDER ORDER

The successor of a node with a right child is easy — the leftmost node of that subtree. The case that catches people is a node with no right child, where the answer is not below it at all: it is the deepest ancestor the walk turned left at. Rather than special-casing the two shapes, this walks from the root once and records a candidate whenever it turns left. Same shape as ceil, and it needs no parent pointers.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
75 / PROBLEM #12 · CANDIDATE · MED

Inorder Successor/Predecessor in BST

MED candidate ▶ SOLVE ON LEETCODE PREMIUM
SIGNAL — WHAT GIVES IT AWAY

“The next value after this one, in sorted order”

INTUITION

With a right child the answer is the leftmost node of that subtree. Without one it is not below the node at all — it is the deepest ancestor the walk turned left at. Rather than special-case the shapes, walk from the root once and record a candidate on every left turn.

STEPS
  1. Start with no candidate
  2. If the node's value is greater than the key, record it and go LEFT
  3. Otherwise it cannot be the successor — go RIGHT
  4. Return the last candidate recorded
  5. Predecessor is the mirror: record on smaller, then go right
BRUTEO(n) in-order into an array
OPTIMALO(h)
↕ SCROLL
Node* successor(Node* root, Node* p) {
    Node* best = nullptr;
    while (root) {
        if (root->val > p->val) { best = root; root = root->left; }
        else root = root->right;
    }
    return best;
}
TIMEO(h)one comparison per level
SPACEO(1)no parent pointers needed
TRAP

Using >= lets a present key be its own successor. Successor is STRICTLY greater; ceil is the one that allows equality.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
76 / INTRO UNIT 12 · THE CONTROLLED STACK

UNIT 12 — THE CONTROLLED STACK

An in-order traversal you can pause, in O(h) space

THE QUESTION THIS LECTURE ANSWERS

HOW DO YOU HAND BACK ONE SORTED VALUE AT A TIME WITHOUT FLATTENING?

iteratorleft spineamortised
WHAT TO WATCH FOR
  • 01THE INTERFACE IS next() AND hasNext() — IT MUST PAUSE
  • 02FLATTENING TO A VECTOR IS CORRECT AND COSTS O(n)
  • 03THE STACK HOLDS ONLY THE LEFT SPINE OF WHAT REMAINS
  • 04PUSHED ONCE, POPPED ONCE — next() IS AMORTISED O(1)
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
77 / VIDEO UNIT 12 · THE CONTROLLED STACK

L50. Binary Search Tree Iterator

STRIVER A2Z
THE CONTROLLED STACK
RUNTIME 14:00
AFTER THIS → 3 DRILLS · CONCEPT UNIT
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
78 / DRILL UNIT 12 · THE CONTROLLED STACK · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture names the two operations the iterator has to support. Which?

next() and hasNext(). That interface is what forces the design: the traversal has to be pausable, giving one value and then stopping until asked again. A plain recursive in-order cannot pause, which is why the recursion has to be turned into an explicit stack.

DRILL 02 · TRANSFER

Flattening the tree into a sorted vector in the constructor also satisfies the interface. Why is it rejected?

Space. Flattening is correct and easy and costs O(n) — which is the entire difficulty of the problem thrown away. The stack holds only the left spine of what remains, so it never exceeds the height. On a balanced tree with 10⁵ nodes that is 17 pointers rather than 100000.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
79 / DRILL UNIT 12 · THE CONTROLLED STACK · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRACE

Each node is pushed once and popped once across a full traversal. What does that make next()?

Amortised O(1), and the distinction is the point. A single next() can push a long left spine and cost O(h). But across the whole traversal each node is pushed and popped exactly once, so n calls cost O(n) total. Claiming worst-case O(1) in an interview is the wrong answer to a question they are asking on purpose.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
80 / MECHANISM UNIT 12 · BSTITER · CODE MIRRORED

O(H) SPACE, BY REFUSING TO WALK AHEAD

Flattening the tree into a sorted array makes next() trivial and costs O(n) memory, which is the whole difficulty of the problem thrown away. The iterator instead keeps a stack holding only the left spine of what remains: the constructor pushes root, root->left, root->left->left … and next() pops one and pushes the left spine of its right child. The stack never exceeds the height. Each node is pushed once and popped once across the whole traversal, so next() is amortised O(1) — individual calls are not.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
81 / INTRO UNIT 13 · MERGE TWO SORTED WALKS

UNIT 13 — MERGE TWO SORTED WALKS

Two BSTs are two sorted sequences, and you already know how to merge those

THE QUESTION THIS LECTURE ANSWERS

CAN YOU MERGE TWO BSTs WITHOUT BUILDING A THIRD TREE?

mergetwo sorted listsiterator
WHAT TO WATCH FOR
  • 01THIS ROW HAS NO LECTURE — THE DRILLS CHECK THE INTRO INSTEAD
  • 02IN-ORDER OF EACH TREE IS ALREADY SORTED
  • 03THE ARRAY VERSION IS O(n+m) TIME AND O(n+m) SPACE
  • 04TWO ITERATORS KEEP THE TIME AND DROP THE SPACE TO O(h1+h2)
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
82 / DRILL UNIT 13 · MERGE TWO SORTED WALKS

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

This row has no lecture in the playlist. Given in-order is sorted, what does merging two BSTs reduce to?

The merge step of merge sort. Once in-order-is-sorted has landed, this stops being a tree problem: two BSTs are two sorted sequences. Inserting one tree into the other is O(n log m) at best and O(n·m) on a chain, and it rebuilds structure you were handed.

DRILL 02 · TRANSFER

Collecting both in-orders into arrays and merging is O(n+m) time. What does driving two iterators instead buy?

Space, not time. Both are O(n+m) time — you must touch every value. The iterators from unit 12 hold only two left spines, so the memory is the two heights rather than the two trees. It is also why unit 12 is in this deck despite having no sheet row of its own.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
83 / MECHANISM UNIT 13 · BSTMERGE · CODE MIRRORED

TWO SORTED SEQUENCES, WHICH YOU ALREADY KNOW HOW TO MERGE

Once in-order-is-sorted has landed, this problem stops being about trees. Two BSTs are two sorted sequences; merging them is the merge step of merge sort. The lazy version collects both in-orders into arrays and merges — O(n+m) time and O(n+m) space. Driving two iterators from unit 12 instead keeps the time and drops the space to O(h1+h2), and on balanced trees that is the difference between a hundred thousand and thirty-four.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
84 / PROBLEM #13 · INORDER · HARD

Merge 2 BST’s

HARD inorder ▶ SOLVE ON LEETCODE▶ SOLVE ON GEEKSFORGEEKS
SIGNAL — WHAT GIVES IT AWAY

“All elements of two BSTs, in sorted order”

INTUITION

Once in-order-is-sorted has landed, this stops being a tree problem. Two BSTs are two sorted sequences, and merging two sorted sequences is the merge step of merge sort. Driving two iterators instead of two arrays keeps the time and drops the space to the two heights.

STEPS
  1. Open an iterator on each tree
  2. Repeatedly take the smaller of the two current heads
  3. When one runs out, drain the other
  4. The output is sorted by construction — nothing is sorted
BRUTEO((n+m)log(n+m)) concatenate and sort
OPTIMALO(n+m)
↕ SCROLL
vector<int> getAllElements(Node* a, Node* b) {
    vector<int> out; stack<Node*> s1, s2;
    auto push = [](stack<Node*>& s, Node* n) {
        while (n) { s.push(n); n = n->left; } };
    push(s1, a); push(s2, b);
    while (!s1.empty() || !s2.empty()) {
        stack<Node*>& s = s2.empty() ||
            (!s1.empty() && s1.top()->val <= s2.top()->val) ? s1 : s2;
        Node* n = s.top(); s.pop();
        out.push_back(n->val); push(s, n->right);
    }
    return out;
}
TIMEO(n+m)every value touched once
SPACEO(h1+h2)two left spines
TRAP

Inserting one tree's nodes into the other is O(n log m) at best and O(n·m) on a chain — and it rebuilds structure you were already handed.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
85 / INTRO UNIT 14 · TWO SUM, BOTH ENDS

UNIT 14 — TWO SUM, BOTH ENDS

Two pointers, where the array is a tree

THE QUESTION THIS LECTURE ANSWERS

WHY IS A HASH SET THE WRONG ANSWER TO A PROBLEM ABOUT A BST?

two pointersreverse iteratordistinct
WHAT TO WATCH FOR
  • 01THE PREREQUISITE HE NAMES IS TWO SUM — THIS IS THAT, SORTED
  • 02TWO DISTINCT ELEMENTS: THE POINTERS MUST NEVER MEET
  • 03A HASH SET IS O(n) SPACE AND DISCARDS THE ORDERING
  • 04FORWARD AND REVERSE ITERATORS ARE THE TWO ENDS OF A SORTED ARRAY
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
86 / VIDEO UNIT 14 · TWO SUM, BOTH ENDS

L51. Two Sum In BST

STRIVER A2Z
TWO SUM, BOTH ENDS
RUNTIME 15:06
AFTER THIS → 3 DRILLS · PROBLEM #14
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
87 / DRILL UNIT 14 · TWO SUM, BOTH ENDS · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture is emphatic about one constraint on the pair. Which?

Two distinct elements. It is why the two-pointer condition is a < b and not a != b: the pointers must never meet or cross, or a value pairs with itself and k = 2·v is reported as a hit. On LeetCode 653 that is exactly the failing case.

DRILL 02 · RECALL

The lecture names a prerequisite problem. Which?

Two Sum. The point of naming it is that this problem is not new — it is Two Sum on a sorted input, and the tree is only the container the sorted input arrives in. Recognising an old problem in unfamiliar clothing is the skill an OA actually measures.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
88 / DRILL UNIT 14 · TWO SUM, BOTH ENDS · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRANSFER

A hash set also solves this in O(n) time. What does the two-iterator version do better?

Space, by using what you were given. The set is correct and accepted, and it discards the one property the input handed you for free: the values are already in order. Two iterators are the two ends of a sorted array — O(n) time, O(h) space.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
89 / MECHANISM UNIT 14 · BSTTWOSUM · CODE MIRRORED

TWO POINTERS, ON A TREE

The hash-set answer works, is accepted, and costs O(n) extra space — and it throws away the one thing the input handed you for free, which is that the values are already in order. Run a forward iterator and a reverse iterator as the two ends of a sorted array: sum too small, advance the low end; too large, retreat the high end. O(n) time, O(h) space. The condition is a < b, not a != b — the pointers must never cross or pass each other and pair a value with itself.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
90 / PROBLEM #14 · INORDER · HARD

Two Sum In BST | Check if there exists a pair with Sum K

HARD inorder ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Do two distinct nodes sum to k?”

INTUITION

This is Two Sum, and the tree is only the container the sorted input arrives in. A forward iterator and a reverse iterator are the two ends of a sorted array: sum too small, advance the low end; too large, retreat the high end.

STEPS
  1. Open a forward iterator (smallest first) and a reverse one
  2. Take one value from each end
  3. Sum too small: advance the low end
  4. Sum too large: retreat the high end
  5. Equal: found. Pointers crossing: no such pair
BRUTEO(n) time and O(n) space with a hash set
OPTIMALO(n)
↕ SCROLL
bool findTarget(Node* root, int k) {
    BSTIterator lo(root, false), hi(root, true);
    int a = lo.next(), b = hi.next();
    while (a < b) {
        if (a + b == k) return true;
        if (a + b < k) a = lo.next();
        else b = hi.next();
    }
    return false;
}
TIMEO(n)each value passed once
SPACEO(h)two left spines
TRAP

The loop condition must be a < b. Using a != b lets the pointers cross, and a value pairs with itself so k = 2v is reported as a hit.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
91 / INTRO UNIT 15 · RECOVER — TWO VIOLATIONS

UNIT 15 — RECOVER — TWO VIOLATIONS

A sorted sequence with two elements swapped falls in at most two places

THE QUESTION THIS LECTURE ANSWERS

HOW MANY PLACES CAN A TWO-NODE SWAP SHOW UP IN AN IN-ORDER WALK?

dipadjacent swapMorris
WHAT TO WATCH FOR
  • 01THE GUARANTEE IS EXACTLY TWO NODES, SWAPPED
  • 02FAR APART GIVES TWO DIPS; ADJACENT GIVES ONE
  • 03TWO DIPS: FIRST OF THE FIRST, SECOND OF THE LAST
  • 04HANDLING ONLY THE TWO-DIP CASE IS THE STANDARD BUG
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
92 / VIDEO UNIT 15 · RECOVER — TWO VIOLATIONS

L52. Recover BST

STRIVER A2Z
RECOVER — TWO VIOLATIONS
RUNTIME 15:56
AFTER THIS → 3 DRILLS · PROBLEM #15
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
93 / DRILL UNIT 15 · RECOVER — TWO VIOLATIONS · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

What does the problem guarantee about the damage to the tree?

Exactly two, swapped. That guarantee is what makes an O(n) scan sufficient: a sorted sequence with two elements exchanged has at most two places where it falls. Without it you would have to rebuild the tree rather than repair it.

DRILL 02 · TRACE

In-order of the damaged tree reads 12 4 6 8 10 2 14. Which two values must be swapped back?

12 and 2. There are two dips: 12 → 4 and 10 → 2. With two dips the culprits are the first value of the first dip and the second value of the last — 12 and 2. Taking both values from the same dip is the standard error and gives 12 and 4, which is option two for exactly that reason.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
94 / DRILL UNIT 15 · RECOVER — TWO VIOLATIONS · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRANSFER

Your code handles two dips correctly and fails a small test. What shape did you miss?

Adjacent nodes give only ONE dip. Swap two neighbours in a sorted sequence and there is a single fall, from which both culprits come. Code that assumes two dips leaves the second pointer null and crashes or does nothing. It is the smallest test anyone writes, which is why this bug is caught immediately and still written constantly.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
95 / MECHANISM UNIT 15 · BSTRECOVER · CODE MIRRORED

A SORTED LIST WITH TWO SWAPS HAS ONE DIP, OR TWO

Walk in-order and the values should only ever rise. Two nodes swapped produce at most two places where they fall. If the swapped pair is far apart you see two dips, and the culprits are the first value of the first dip and the second value of the last. If the pair is adjacent you see only one dip, and both culprits come from it. Handling only the two-dip case is the standard bug, and it fails on precisely the smallest test case anyone tries.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
96 / PROBLEM #15 · INORDER · HARD

Correct BST with two nodes swapped

HARD inorder ▶ SOLVE ON LEETCODE
SIGNAL — WHAT GIVES IT AWAY

“Exactly two nodes were swapped — put them back”

INTUITION

In-order should only ever rise. Two swapped nodes produce at most two places where it falls. Far apart gives two dips and the culprits are the first value of the first and the second value of the last; adjacent gives one dip and both culprits come from it.

STEPS
  1. Walk in-order, remembering the previously visited node
  2. A value smaller than the previous one is a dip
  3. First dip: record the previous node as first, this one as second
  4. Any later dip: overwrite second with this node
  5. Swap the values in first and second
BRUTEO(n log n) sort and compare
OPTIMALO(n)
↕ SCROLL
Node *first = nullptr, *second = nullptr, *prev = nullptr;
void inorder(Node* n) {
    if (!n) return;
    inorder(n->left);
    if (prev && n->val < prev->val) {
        if (!first) { first = prev; second = n; }
        else second = n;
    }
    prev = n;
    inorder(n->right);
}
void recoverTree(Node* root) {
    inorder(root);
    swap(first->val, second->val);
}
TIMEO(n)one in-order pass
SPACEO(h)the stack — O(1) with Morris
TRAP

Handling only the two-dip case leaves the second pointer null when the swapped pair is adjacent, which is the smallest test anyone writes.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
97 / INTRO UNIT 16 · LARGEST BST INSIDE A TREE

UNIT 16 — LARGEST BST INSIDE A TREE

A parent cannot judge itself until both children have reported

THE QUESTION THIS LECTURE ANSWERS

WHY MUST THIS BE POST-ORDER, AND WHAT HAS TO TRAVEL UPWARD?

post-ordertuplemin/max/size
WHAT TO WATCH FOR
  • 01THE WHOLE TREE FAILS ON A VALUE THAT BEATS ITS PARENT ONLY
  • 02EACH CALL RETURNS MIN, MAX, SIZE AND VERDICT
  • 03A NODE ROOTS A BST IFF BOTH CHILDREN DO AND IT FITS BETWEEN THEM
  • 04VALIDATING EVERY SUBTREE SEPARATELY IS O(n²)
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
98 / VIDEO UNIT 16 · LARGEST BST INSIDE A TREE

L53. Largest BST in Binary Tree

STRIVER A2Z
LARGEST BST INSIDE A TREE
RUNTIME 17:27
AFTER THIS → 3 DRILLS · PROBLEM #16
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
99 / DRILL UNIT 16 · LARGEST BST INSIDE A TREE · 1 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · RECALL

The lecture opens by showing why the whole tree is not a BST. What is its example?

A 7 sitting in the right subtree of 10. It is the unit 08 violation again: legal against its immediate parent, illegal against an ancestor. That is why the recursion must return the subtree's min and max upward — a parent cannot see the values that break it otherwise.

DRILL 02 · TRANSFER

Why must this be post-order rather than pre-order?

The information flows upward. To decide whether it roots a BST, a node needs the left subtree's max, the right subtree's min, and both verdicts — all facts about its children. Pre-order carries information down, which is the wrong direction, and would force a re-scan per node: O(n²) instead of O(n).

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
100 / DRILL UNIT 16 · LARGEST BST INSIDE A TREE · 2 OF 2

CHECK — CAN YOU ANSWER IT WITHOUT LOOKING BACK?

DRILL 01 · TRACE

Tree [10,5,15,1,8,null,7]. What is the largest BST subtree, and how big?

The subtree rooted at 5 — nodes 5, 1 and 8 — size 3. The whole tree fails on 7, which sits right of 10 and does not exceed it. Note what that costs 15: perfectly ordered in itself, ruined by one child, and reduced to a best of 1. A node can be locally fine and still contribute nothing.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
101 / MECHANISM UNIT 16 · BSTLARGEST · CODE MIRRORED

THE PARENT CANNOT JUDGE ITSELF UNTIL BOTH CHILDREN REPORT

Checking each subtree independently with a validator is O(n²). One post-order pass is O(n), and it works because each call returns four facts rather than one: the subtree's min, max, size and verdict. A node is the root of a BST exactly when both children are, and its own value fits strictly between the left's max and the right's min. Watch node 15 here — perfectly ordered in itself, ruined by one child, and reduced to a best of 1.

THE TREE
PANEL
RESULT
CODE MIRROR
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
102 / PROBLEM #16 · BOUNDS · HARD

Largest BST in Binary Tree

HARD bounds ▶ SOLVE ON LEETCODE PREMIUM
SIGNAL — WHAT GIVES IT AWAY

“Largest subtree that is a BST” — inside a tree that is not one

INTUITION

A node cannot judge itself. It needs the left subtree's maximum, the right subtree's minimum and both verdicts — all facts about its children — so the information travels upward and the traversal must be post-order. Each call returns four things instead of one.

STEPS
  1. Recurse into both children first
  2. A null subtree is a BST of size 0, with min +inf and max -inf
  3. This node roots a BST iff both children do AND its value fits between them
  4. If so, its size is left + right + 1 — update the best
  5. If not, return a poisoned range so no ancestor can qualify
BRUTEO(n²) validating every subtree
OPTIMALO(n)
↕ SCROLL
struct Info { int mn, mx, size; bool ok; };
Info go(Node* n, int& best) {
    if (!n) return { INT_MAX, INT_MIN, 0, true };
    Info l = go(n->left, best), r = go(n->right, best);
    if (l.ok && r.ok && n->val > l.mx && n->val < r.mn) {
        int sz = l.size + r.size + 1;
        best = max(best, sz);
        return { min(n->val, l.mn), max(n->val, r.mx), sz, true };
    }
    return { INT_MIN, INT_MAX, max(l.size, r.size), false };
}
TIMEO(n)each node visited once
SPACEO(h)the recursion stack
TRAP

Returning only a boolean is not enough — the parent cannot check its own value without the children's min and max, and re-computing those is what makes the naive version quadratic.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
103 / RECALL RETRIEVAL, NOT RECOGNITION · 1 OF 3

NAME THE WALK FROM WHAT IS ASKED

DRILL 01 · RECALL

A problem says “return the smallest value greater than or equal to X”. Which shape?

Carry a candidate. The key may be absent, so the walk cannot just return where it stops — the answer is the last node that could still have been it. Ceil, floor and successor are all this one shape, which is why they are three units and one idea.

DRILL 02 · RECALL

Which of these genuinely requires post-order rather than any other traversal?

Largest BST subtree. A node cannot decide whether it roots a BST until both children report their min, max, size and verdict — the information travels upward, which is what post-order is. Kth is in-order, LCA is a walk down, and validation can be done either by a downward window or an in-order scan.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
104 / RECALL RETRIEVAL, NOT RECOGNITION · 2 OF 3

NAME THE WALK FROM WHAT IS ASKED

DRILL 01 · TRANSFER

Given a BST and a target k, you must decide if two distinct nodes sum to k. Which costs least space?

Two iterators — O(h) space. The vector and the hash set are both O(n) and both discard the fact that the input is already ordered. The iterators are the two ends of a sorted array without ever materialising the array, which is the whole reason unit 12 is in this deck.

DRILL 02 · RECALL

Deleting a node with two children, you copy the in-order successor's value up. What must happen next?

Delete the successor. Copying the value leaves that value in the tree twice, so the original has to go — and because the successor is the leftmost node of the right subtree, it has no left child and falls into the easy case. That reduction is why the hard case is not actually hard.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
105 / RECALL RETRIEVAL, NOT RECOGNITION · 3 OF 3

NAME THE WALK FROM WHAT IS ASKED

DRILL 01 · TRANSFER

You must return values in sorted order but the caller may stop at any point. Which design?

The controlled stack. Flattening costs O(n) memory and throws the problem away; re-running the traversal costs O(n) per value. The stack holds only the left spine of what remains — O(h) — and each node is pushed and popped once, so next() is amortised O(1).

DRILL 02 · RECALL

Which single fact does the biggest share of this deck rest on?

In-order is sorted. Kth smallest, validate, recover, merge, two-sum and the iterator are all that one fact used differently — six of the sixteen rows, and the hardest four among them. The others are true and local; this one is the bridge from “tree” to “sorted sequence”, and it is what the rest is built on.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
106 / TRAPS PLAUSIBLE, WRONG, AND SILENT

SIX WAYS TO BE PLAUSIBLY WRONG

Not one of these crashes. Every one returns something that looks like an answer — a validator that accepts an invalid tree, a minimum that is not the minimum, a counter that only ever reaches one. That is what makes them expensive.

THE VALIDATOR THAT ONLY LOOKS AT CHILDREN

node->left->val < node->val at every node returns TRUE on trees that are not BSTs. A 6 under a 12 in the right subtree of an 8 satisfies its parent and breaks its grandparent. Carry a window down instead — and unit 08's bench is that exact tree.

INT_MIN AS A SENTINEL BOUND

valid(root, INT_MIN, INT_MAX) looks airtight and rejects a valid tree containing INT_MIN, because the node fails val <= lo against its own value. Use long, or pass nullable bounds and skip the comparison when one is absent.

THE MINIMUM IS NOT A LEAF

The leftmost node cannot have a left child; it can perfectly well have a right one. Code that loops while(n->left && n->right) or tests isLeaf stops early and returns a value that is not the minimum, silently, on exactly that shape.

RECORDING THE CANDIDATE THEN WALKING THE WRONG WAY

In ceil, a qualifying node means the answer is this or something SMALLER, so you go left. Going right keeps the first qualifier and returns a value that is too large. Floor is the mirror, and flipping only one of the comparison and the direction is the way this gets written wrong.

THE Kth COUNTER DECLARED INSIDE THE RECURSION

A local counter resets in every subtree, so ++cnt == k only ever fires for k = 1. It has to outlive the recursion — a reference parameter or a member. The answer that comes back is a real node's value, which is what makes it hard to see.

RECOVER THAT ONLY HANDLES TWO DIPS

Two swapped nodes give two dips when they are far apart and ONE when they are adjacent. Code written for the two-dip case leaves the second pointer null on the adjacent case — and adjacent is the smallest test anybody writes.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
107 / CHEATSHEET REVISION SURFACE

ONE SCREEN, THE WHOLE DECK

Every operation in this step with its cost and the one line that selects it. This is the night-before page.

ALGORITHM
TIME
SPACE
REACH FOR IT WHEN
Search / insert
O(h)
O(1) iterative
one comparison per level; insert is the search that ended in a null
Find min / max
O(h)
O(1)
walk left (or right) until you cannot — no comparison at all
Ceil / floor / successor
O(h)
O(1)
record the last node that qualified, then keep hunting tighter
Delete
O(h)
O(h) recursive
0 or 1 child unhooks; 2 children copies the successor up and deletes it
Kth smallest
O(k)
O(h)
in-order with a counter, and stop the moment it reaches k
Validate
O(n)
O(h)
a window per node, or an in-order that must strictly increase
LCA
O(h)
O(1) iterative
walk while both agree; the first disagreement IS the answer
Build from preorder
O(n)
O(h)
one pass with an upper bound — the bound marks where a subtree ends
BST iterator
O(1) amortised
O(h)
a stack holding only the left spine of what has not been returned
Merge two BSTs
O(n+m)
O(h1+h2)
two iterators, merged as two sorted sequences
Two sum
O(n)
O(h)
forward and reverse iterators as the two ends of a sorted array
Recover
O(n)
O(h)
in-order; two dips means far apart, one dip means adjacent
Largest BST subtree
O(n)
O(h)
post-order returning min, max, size and verdict from each child
INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
108 / CLOSE 14 · BINARY SEARCH TREES

THE ORDERING IS THE ALGORITHM

A binary search tree is a binary tree with one promise held at every node, and every problem in this step is that promise cashed in. Six of them are a walk down, where one comparison names a direction and the other subtree is never seen. The other nine are the same observation twice removed: in-order emits sorted values, so counting, validating, repairing, merging and pairing are all questions about a sorted list that never gets built. Next is step 15, graphs, where nothing is ordered and the walk has to remember where it has been.

00%
OF THIS DECK SOLVED
← ALL TOPICSTHE SHELFSTEP 13 · BINARY TREES

Step 14, all 16 sheet rows, 15 lectures (L39–L53). Unit 12 is a lecture with no sheet row; unit 13 is a sheet row with no lecture. Every bench fills in values the build re-derived and asserted, and every drill that quotes a lecture is checked verbatim against its transcript — except in units 3, 6, 8 and 13, where no usable transcript exists and the drills cite the moment instead.

INVARIANT · BST · Binary Search Trees · BINARY SEARCH TREES
■ TOO SMALL TO READ
1280×720
INVARIANT · 14 · BINARY SEARCH TREES

This one needs a laptop

Not a preference — an arithmetic one. Every slide is a fixed 1280 × 720 stage: a graph animating beside the code that drives it, with the problems laid out two columns wide. It scales as a single piece, so on a screen this size the body text comes out around 4px tall.

Shrinking it further would not help, and rebuilding it to reflow would mean losing the thing that makes it worth reading.

YOUR SCREEN0 × 0
NEEDED1060 × 610
WHAT IS WAITING ON THE LAPTOP
The sheet, taught.
Your progress is saved per device, so anything you tick on the laptop will be waiting there.