FAANG Interview Prep
Foundations, Memory & Complexity
Big-O notation, time/space analysis, memory layoutRecursion Complete Guide
Base cases, call stack, tail recursion, memoizationArrays & Array ADT
Static/dynamic arrays, operations, amortized analysisStrings
Pattern matching, string algorithms, encoding, manipulationMatrices
2D arrays, sparse matrices, matrix operations, traversalsLinked Lists
Singly, doubly, circular lists, pointer manipulationStack
LIFO, push/pop, expression evaluation, backtrackingQueue
FIFO, circular queue, deque, priority queueTrees
Binary trees, traversals, expression trees, threaded treesBST & Balanced Trees
Search, insert, delete, AVL, red-black, B-treesHeaps, Sorting & Hashing
Min/max heaps, heapsort, hash tables, collision handlingGraphs, DP, Greedy & Backtracking
BFS, DFS, shortest paths, dynamic programming, optimizationIntroduction to Binary Search Trees
A Binary Search Tree (BST) is a binary tree with an ordering property: for every node, all values in the left subtree are smaller, and all values in the right subtree are larger. This property enables efficient \(O(\log n)\) average-case operations.
BST Property
For every node N: left_subtree_values < N.val < right_subtree_values
This invariant must hold for the entire subtree, not just immediate children!
BST Node Structure
BST Operations
Search Operation
BST search exploits the ordering invariant: at each node, if the target is smaller, go left; if larger, go right. This eliminates half the remaining tree at every step — exactly like binary search on a sorted array, but on a tree structure. Average time: \(O(\log n)\). Worst case (degenerate/skewed tree): \(O(n)\) — which is why balanced variants (AVL, Red-Black) exist.
Iterative vs Recursive: Both work identically. Iterative uses \(O(1)\) space; recursive uses \(O(h)\) call stack space (where \(h\) = tree height). In interviews, iterative is preferred for search since it's simpler and avoids stack overflow on very deep trees.
Insert Operation
Insertion follows the same path as search — descend left/right until you find a null position, then attach the new node there. The new node is always inserted as a leaf. This maintains the BST property without rearranging existing nodes (unlike balanced trees which may rotate after insert). Average: \(O(\log n)\). If elements are inserted in sorted order, the tree degenerates to a linked list — \(O(n)\) per operation.
Delete Operation
BST Deletion Cases
- Case 1 - Leaf node: Simply remove the node
- Case 2 - One child: Replace node with its child
- Case 3 - Two children: Replace with inorder successor (or predecessor)
Inorder Successor & Predecessor
The inorder successor of a node is the next node in sorted order — the smallest value greater than the current node. Two cases: (1) If the node has a right subtree, the successor is the leftmost node in the right subtree. (2) If no right subtree, walk up to the first ancestor where the node is in its left subtree. This concept is critical for BST deletion (Case 3) and for building iterators over BSTs.
BST Validation
AVL Trees
AVL Tree is a self-balancing BST where the height difference between left and right subtrees (balance factor) is at most 1 for every node. Named after inventors Adelson-Velsky and Landis.
AVL Property
Balance Factor = height(left subtree) - height(right subtree)
Valid balance factors: -1, 0, +1
If |balance factor| > 1, tree needs rebalancing via rotations.
AVL Node Structure
AVL Rotations
Four Types of Rotations
| Imbalance | Rotation | When to Use |
|---|---|---|
| Left-Left (LL) | Right Rotation | balance > 1 AND left balance >= 0 |
| Right-Right (RR) | Left Rotation | balance < -1 AND right balance <= 0 |
| Left-Right (LR) | Left then Right | balance > 1 AND left balance < 0 |
| Right-Left (RL) | Right then Left | balance < -1 AND right balance > 0 |
flowchart TD
A["Insert/Delete Node"] --> B{"Update Heights"}
B --> C{"Balance Factor?"}
C -->|"BF > 1
(Left Heavy)"| D{"Left Child BF?"}
C -->|"-1 ≤ BF ≤ 1
(Balanced)"| E["No Rotation Needed"]
C -->|"BF < -1
(Right Heavy)"| F{"Right Child BF?"}
D -->|"≥ 0 (LL Case)"| G["Right Rotate"]
D -->|"< 0 (LR Case)"| H["Left Rotate Child →
Right Rotate Node"]
F -->|"≤ 0 (RR Case)"| I["Left Rotate"]
F -->|"> 0 (RL Case)"| J["Right Rotate Child →
Left Rotate Node"]
G --> K["Tree Balanced ✓"]
H --> K
I --> K
J --> K
Interactive: AVL Left Rotation (RR Case)
Step through a left rotation to see how an unbalanced RR case is resolved. Use the Next button to advance each stage.
AVL Left Rotation — Step-Through
After inserting node X, Z has balance factor -2. Click Next to walk through the left rotation.
Complete AVL Insert with All Cases
Red-Black Trees
Red-Black Tree is another self-balancing BST with less strict balancing than AVL. It uses node coloring to maintain approximate balance, guaranteeing \(O(\log n)\) operations.
Red-Black Properties
- Every node is either RED or BLACK
- Root is always BLACK
- All leaves (NIL nodes) are BLACK
- Red node cannot have red children (no two reds in a row)
- Every path from root to leaf has same number of black nodes (black height)
Tree Comparison
BST vs AVL vs Red-Black
| Property | BST | AVL | Red-Black |
|---|---|---|---|
| Search | O(h) - \(O(n)\) worst | \(O(\log n)\) | \(O(\log n)\) |
| Insert | O(h) | \(O(\log n)\) | \(O(\log n)\) |
| Delete | O(h) | \(O(\log n)\) | \(O(\log n)\) |
| Balance | None | Strict (±1) | Relaxed |
| Rotations | None | More frequent | Less frequent |
| Best for | Static data | Lookups | Insert/Delete heavy |
| Used in | Simple apps | Databases | Java TreeMap, C++ map |
Interview Patterns
BST interview problems exploit one key insight: inorder traversal of a BST produces sorted output. This means "K-th smallest" becomes "K-th node in inorder", "validate BST" becomes "check inorder is strictly increasing", and range queries become bounded traversals. The problems below are among the most frequently asked BST questions at FAANG companies.
Kth Smallest Element in BST
Perform inorder traversal and count nodes visited. When the counter reaches \(k\), you've found the K-th smallest. Iterative inorder with an explicit stack gives \(O(H + k)\) time where \(H\) is tree height — you don't need to traverse the entire tree, just descend to the leftmost path then pop \(k\) nodes. For repeated queries, augmenting each node with subtree size gives \(O(\log n)\) per query.
Lowest Common Ancestor in BST
In a BST, finding the LCA is elegant: start at the root and leverage the ordering property. If both nodes are smaller than current, LCA is in the left subtree. If both are larger, it's in the right subtree. If they split (one goes left, one goes right), the current node IS the LCA. This gives \(O(h)\) time — no need for parent pointers or marking ancestors. Note: this BST-specific approach doesn't work for general binary trees (which require a different technique).
Convert Sorted Array to BST
To build a height-balanced BST from a sorted array, use the middle element as root (this ensures equal nodes on each side), then recursively build left and right subtrees from the left and right halves. This is the inverse of inorder traversal — it produces a balanced tree in \(O(n)\) time with \(O(\log n)\) recursion depth. The same technique works for converting sorted linked lists to BSTs.
Search in BST
This is a warm-up problem that tests whether you understand the BST invariant. Both recursive and iterative solutions are expected — the iterative version is often preferred in interviews for its \(O(1)\) space. The key extension: Search in BST + Insert (LeetCode 701) combines search with insertion at the correct null position.
LeetCode Practice Problems
Essential BST Problems
| # | Problem | Difficulty | Key Concept |
|---|---|---|---|
| 98 | Validate Binary Search Tree | Medium | BST validation with bounds |
| 700 | Search in a Binary Search Tree | Easy | Basic BST search |
| 701 | Insert into a Binary Search Tree | Medium | BST insertion |
| 450 | Delete Node in a BST | Medium | BST deletion with 3 cases |
| 230 | Kth Smallest Element in a BST | Medium | Inorder traversal |
| 235 | Lowest Common Ancestor of a BST | Medium | BST property for LCA |
| 108 | Convert Sorted Array to BST | Easy | Balanced BST construction |
| 109 | Convert Sorted List to BST | Medium | Two pointers + recursion |
| 653 | Two Sum IV - Input is a BST | Easy | BST + Hash Set |
| 1382 | Balance a Binary Search Tree | Medium | Inorder + rebuild balanced |
Complete DSA Series
FAANG Interview Preparation
Quick Check — Test Yourself
- Draw an AVL tree after inserting 10, 20, 30 in order. Which rotation is triggered?
- What is the maximum height of an AVL tree with n nodes? How does this compare to a degenerate BST?
- Why do Red-Black trees use at most 2 rotations per insertion while AVL trees may need \(O(\log n)\)?
Common Bugs
- Forgetting to update height after rotation: In AVL, heights must be recomputed bottom-up after every rotation. A stale height field causes incorrect balance factors.
- Off-by-one in balance factor: Balance factor = height(left) − height(right). An empty subtree has height −1 (not 0).
- BST delete without maintaining BST property: When deleting a node with two children, replace with in-order successor (or predecessor) — any other replacement breaks the BST ordering.
Interview Lens
Interviewers rarely ask you to implement AVL rotations from scratch — they test understanding. Know: (1) which rotation each imbalance case requires (LL, RR, LR, RL), (2) that AVL gives \(O(\log n)\) worst case for all operations, (3) that Red-Black is preferred in practice due to fewer rebalancing operations on insertion-heavy workloads.
Production Lens
Java’s TreeMap and C++’s std::map/std::set are Red-Black trees. Linux kernel’s CFS scheduler uses a Red-Black tree keyed by virtual runtime. Linux’s virtual memory manager (VMA) uses Red-Black trees for interval lookups. AVL trees appear in databases (e.g. embedded use cases) where read-heavy workloads benefit from stricter balancing.
Next in the Series
In Part 11: Heaps, Sorting & Hash Tables, we'll explore heap-backed priority queues, the comparison sorting algorithms (merge, quick, heap), and hash tables — the three workhorses of practical algorithm design.