Intermediate
intermediate
Foundations
Big-Omega Notation (Lower Bound)
If `O(n)` is the worst-case ceiling on an algorithm's running time, what tells you the floor, the absolute minimum work the algorithm must always do? That is the question **Big-Omega Notation** answers, and it is the second pillar of asymptotic analysis that turns half a description of performance into the full picture. This lesson introduces `Omega(g(n))` as a formal lower bound, with the mirror-image definition of Big-O: there exist positive constants `c` and `n0` such that `f(n) >= c * g(n)` for all `n >= n0`. You will practice proving Omega claims, analyze the best-case behavior of familiar algorithms (linear search, bubble sort, insertion sort), and meet a famous problem lower bound: any comparison-based sort must do at least `Omega(n log n)` comparisons in the worst case. You will also learn to spot when an algorithm is asymptotically optimal because its upper and lower bounds coincide. This lesson builds directly on **Big-O Notation (Upper Bound)**, where you learned to express upper bounds on growth using constants `c` and `n0`. Big-Omega flips the inequality from `<=` to `>=` and reuses the same machinery to describe floors instead of ceilings. Once you are comfortable bracketing algorithms with both bounds, you will be ready for **Big-Theta Notation (Tight Bound)**, where the upper and lower bounds meet to give the most precise complexity statement possible.
Not Started
0%
Big-Theta Notation (Tight Bound)
When you can say *both* that an algorithm runs in `O(n log n)` and that it must do at least `Omega(n log n)` work, the ceiling and floor have collapsed onto the same growth rate. That coincidence is the most informative complexity statement you can make, and it is what **Big-Theta Notation** captures in a single symbol. This lesson defines `Theta(g(n))` as the intersection of Big-O and Big-Omega: there exist positive constants `c1`, `c2`, and `n0` such that `c1 * g(n) <= f(n) <= c2 * g(n)` for all `n >= n0`, the so-called sandwich property. You will practice classifying functions and algorithms by their tight bound, learn when Big-Theta is appropriate (best and worst case have the same growth rate) versus when only Big-O is honest (the cases differ), and see why merge sort is `Theta(n log n)` while linear search is *not* Theta of any single function. This lesson stitches together two ideas you have already met. From **Big-O Notation (Upper Bound)** you have the ceiling `f(n) <= c * g(n)`, and from **Big-Omega Notation (Lower Bound)** you have the floor `f(n) >= c * g(n)`. Big-Theta simply requires both bounds to hold for the same `g(n)`, so an algorithm only earns a Theta label when its upper and lower bounds genuinely match. With all three asymptotic notations in hand, you will be ready to switch focus to **Memory Models**, where the same growth-rate thinking gets applied to space rather than time.
Not Started
0%
Combinatorics Basics
How many ways can you arrange `n` items? How many subsets does a set of size `n` have? Questions like these are not idle puzzles, they are exactly the questions you have to answer to know whether a brute-force solution will run in milliseconds or in millennia. **Combinatorics Basics** gives you the counting tools that turn vague statements like "try every possibility" into precise complexity claims. This lesson covers the four counting ideas you will rely on throughout DSA. The **rule of sum** and **rule of product** let you decompose multi-step processes and count outcomes; **permutations** count ordered arrangements (`n!` for arranging all of them, `nPr` for choosing `r` in order); **combinations** count unordered selections (`nCr`, also written as binomial coefficients); and **Pascal's triangle** plus a first look at **basic probability** tie everything together. You will see why a set of size `n` has `2^n` subsets, why generating all permutations of an array is `O(n!)`, and how counting principles directly produce the time complexity of backtracking algorithms. This lesson builds on **Discrete Mathematics Basics**, where you formalized sets, set operations, and logic. Combinatorics is what happens when you start asking "how many?" about those sets, ordered or unordered, with or without repetition. With the counting toolkit in place you will continue the math track in **Number Theory Fundamentals**, picking up primes, divisibility, and `gcd`, the other half of the math you need for hashing, cryptography-style problems, and modular arithmetic.
Not Started
0%
Discrete Mathematics Basics
Almost every conditional you have ever written is a tiny piece of propositional logic, and almost every collection you have ever stored is, mathematically, a set. **Discrete Mathematics Basics** makes that connection explicit, giving you the formal vocabulary that data structures, graph algorithms, database queries, and correctness arguments all sit on top of. This lesson walks you through three pillars of discrete math used throughout DSA. First, **sets** and the operations on them: union, intersection, difference, complement, subset, and membership, the same ideas baked into hash sets and array problems. Second, **propositional logic**: the operators `AND`, `OR`, `NOT`, and implication, plus truth tables for evaluating compound expressions; this is the math behind every Boolean condition in your code. Third, **binary relations** and their properties (reflexive, symmetric, transitive), which generalize the way edges connect nodes in graphs and rows connect in databases. Along the way you will get a first taste of formal proof: how to argue that two sets are equal or that a logical equivalence always holds. This lesson assumes only basic programming familiarity, so no specific DSA prerequisite is required. If you have written `if (x && !y)` or used a hash set, you already have informal intuition for everything we will formalize here. From here you will move into **Combinatorics Basics**, where you will use these set and counting foundations to count permutations, combinations, and arrangements (the math behind backtracking and many complexity proofs).
Not Started
0%
Memory Models
Why does a deeply recursive function crash with a stack overflow while an equivalent loop happily processes a million elements? Why does passing an array into a function sometimes mutate the caller's data and sometimes not? The answers all live one level below your code, in the runtime **memory model** that decides where every variable, object, and function call physically lives. This lesson opens up that model. You will see the difference between the **stack** (small, fast, organized into per-call frames) and the **heap** (larger, manually or garbage-collected, where objects and arrays actually live), watch how every function call pushes a stack frame and every `return` pops one, and trace how recursion stacks frames on top of frames until the base case unwinds them. You will also meet references and pointers conceptually, learn what triggers a stack overflow, and get a working mental model of garbage collection and memory leaks. This lesson builds on **Space Complexity Fundamentals**, where you learned to count auxiliary versus total space and saw why some algorithms claim `O(1)` space while others need `O(n)`. Memory Models gives you the underlying picture: those `O(...)` numbers describe stack frames, heap allocations, and reference graphs that you can now visualize concretely. Next, you will pivot to the mathematical side of the foundations track with **Discrete Mathematics Basics**, picking up the sets, relations, and logic vocabulary that algorithm analysis depends on.
Not Started
0%
Number Theory Fundamentals
Why are hash table sizes almost always prime? Why does the Euclidean algorithm for `gcd` run in `O(log(min(a, b)))` time despite using only subtraction or remainders? **Number Theory Fundamentals** is the branch of math that answers these questions and quietly powers a surprising amount of practical software, from hashing and cryptography to scheduling and competitive programming shortcuts. This lesson introduces the core building blocks. You will study **prime numbers** and how to test primality efficiently, the **divisibility** relation and quick rules for spotting divisors, **GCD** (greatest common divisor) and **LCM** (least common multiple) with the identity `lcm(a, b) = a * b / gcd(a, b)`, and the **Euclidean algorithm** for computing `gcd` in logarithmic time. You will also do **prime factorization** by trial division (`O(sqrt(n))`) and see how factorizations make divisor counting, simplification, and periodicity arguments straightforward. This lesson builds on **Discrete Mathematics Basics**, where you learned how to reason precisely about sets, relations, and logical claims. Number theory uses that same proof-style reasoning, but applied to the integers and their multiplicative structure. With primes, `gcd`, and factorization in your toolkit, you will be ready to take the premium step into **Modular Arithmetic**, where you will reuse all of these ideas to work with `mod`, modular inverses, and Fermat's Little Theorem.
Not Started
0%
Data Structures
Binary Search Tree (BST)
Run an inorder traversal on a **Binary Search Tree (BST)** of any size and the keys come out sorted, in `O(n)` time and `O(h)` space, with no separate sort step. That single property (an ordering invariant baked into the structure itself) is what turns a generic binary tree into a logarithmic-time search container that powers Java's `TreeMap`, C++ `std::map`, and the conceptual model behind every database index. This lesson covers the BST property (left subtree keys less than the node, right subtree keys greater), search and insert that follow the invariant, the three deletion cases (leaf, one child, two children resolved by inorder successor or predecessor), and the validation problem that interviewers love because the naive `node.left.val < node.val` check is wrong. You will also analyze the gap between the balanced `O(log n)` and the degenerate `O(n)` chain that motivates the next lesson. In **Trees: Binary Tree Fundamentals**, you implemented preorder, inorder, postorder, and level-order traversals; the BST property is what makes inorder special, because it now produces sorted output for free. Next, **Balanced BST (AVL / Red-Black)** addresses the elephant in the room: an unlucky insertion order can degrade a BST to a linked list, and self-balancing rotations are the fix.
Not Started
0%
Circular Linked List
An operating system rotating turns among four CPU-bound processes, a music player on shuffle-repeat, and the classic Josephus problem all share the same shape: a finite list of items consulted in cyclical order, where 'after the last' means 'back to the first'. A **Circular Linked List** encodes that shape directly, with the last node's `next` pointer wired to the head instead of `null`. This lesson covers the circular singly linked list and its doubly linked variant, the stop condition for traversal (return to the starting node rather than waiting for `null`), insertion at the head and at the tail in `O(1)` when a tail pointer is maintained, and deletion that correctly handles the wrap-around. You will also compare circular structures with the standard linear forms so you know when bending the list back on itself is the right call and when it just complicates traversal. In **Linked Lists (Singly)**, traversal terminated when you reached a `null` next pointer; here, the same loop must compare against the starting node instead, a small change that exposes the distinction between cycle detection and cycle definition (Floyd's tortoise-and-hare reuses this idea later). With all three linked-list shapes covered, the curriculum next pivots to tree-based and array-based structures with stronger time guarantees.
Not Started
0%
Doubly Linked List
Deleting a node from a singly linked list when you only hold a pointer to that node is genuinely awkward: you need the previous node too, and finding it is `O(n)`. Add a `prev` pointer to every node and the same delete becomes four pointer rewires in `O(1)`, which is exactly the upgrade that powers LRU caches and the browser back-forward stack. This lesson covers the **Doubly Linked List** node layout (`value`, `next`, `prev`), bidirectional traversal, insertion at head and tail and after a given node, deletion by node reference and by value, and the sentinel (dummy head and tail) pattern that eliminates almost all null-check edge cases in pointer-heavy code. You will also weigh the per-node memory cost of the extra pointer against the operations it unlocks. In **Linked Lists (Singly)**, head insertion was already `O(1)` but mid-list deletion required carrying a trailing pointer during traversal. The doubly linked list removes that constraint: every node knows its predecessor, so you can splice it out without any extra bookkeeping. Next, **Circular Linked List** keeps a single direction of links but bends the list back on itself, which turns out to be the right shape for round-robin scheduling and circular buffers.
Not Started
0%
Hash Table (Advanced)
Python's `dict` uses open addressing with a Robin Hood-inspired probe. Java's `HashMap` switches a bucket from a linked list to a red-black tree once chain length crosses eight. C++ `std::unordered_map` is required by the standard to use chaining. Three production hash tables, three different choices, all defending the same goal: keep expected `O(1)` lookups even as the table fills up. **Hash Table (Advanced)** unpacks the engineering decisions behind those choices. This lesson covers hash function design (division method, multiplication method, universal hashing), the two collision-resolution families (separate chaining and open addressing with linear, quadratic, or double hashing), the load-factor threshold that triggers a rehash, and the amortized `O(1)` cost of dynamic resizing. You will also see how tombstones make deletion correct under open addressing, and why Robin Hood and cuckoo hashing tame worst-case probe lengths. In **Hash Map (Dictionary) Basics**, you used a hash map as a black box; this lesson opens the box and replaces the hand-wave with a quantitative model. **Modular Arithmetic** is the workhorse behind every practical hash function: the `key % m` step that turns an arbitrary integer into a valid bucket index, and the `(h(k) + i*step) % m` formula behind double hashing. Next, **Skip List** answers the same fast-lookup question with a probabilistic, pointer-based design that has no hash function at all and no rehashing step.
Not Started
0%
Heaps & Priority Queue
Pull the next task in priority order from a stream of millions, and a sorted array gives you `O(1)` extract but `O(n)` insert; a sorted linked list flips the costs but stays linear; a balanced BST hits `O(log n)` for both but with substantial pointer overhead. A **Heap** quietly outperforms all three for this exact workload by storing a complete binary tree in a flat array and keeping just the min (or max) at the root. This lesson covers the heap property, the parent-and-child index formulas (`parent = (i-1)/2`, `left = 2i+1`, `right = 2i+2`) that let array indices encode tree structure with no pointers, sift-up and sift-down for `O(log n)` insert and extract, and the linear-time `heapify` build. You will see how this maps onto the priority queue abstraction and onto interview staples such as top-K elements, K-th largest, merge K sorted lists, and the streaming median with two heaps; on the systems side, the same structure powers Dijkstra and Prim. In **Trees: Binary Tree Fundamentals**, you saw what a complete binary tree is and how to traverse one; the heap reuses that exact shape but stores it implicitly. **Arrays & Strings** is what makes the implicit storage cheap: a flat array gives `O(1)` parent and child access through arithmetic, with no allocations per node. Next, **Binary Search Tree (BST)** trades the heap's partial ordering for a full ordering invariant, unlocking sorted iteration and key-based search at the cost of needing actual pointers.
Not Started
0%
LRU Cache (Hash Map + DLL)
Hold a fixed number of recently used items, evict the least-recently-touched one when you run out of room, and answer both `get(key)` and `put(key, value)` in `O(1)`. No single primitive does that: a hash map gives `O(1)` lookup but no recency order, and a doubly linked list gives `O(1)` recency moves but no key index. The classical **LRU Cache** wires the two together so each compensates for what the other lacks. This lesson designs the composite from scratch: a hash map that points keys to DLL nodes, and a doubly linked list that orders nodes by recency with most-recent at the head and least-recent at the tail. You will trace `get` and `put` through both structures, handle the capacity-of-one and update-existing-key edge cases, and see why this design appears in browser caches, database query caches, OS page replacement, and CDNs. In **Hash Map (Dictionary) Basics**, you used a hash map for `O(1)` lookup by key. **Doubly Linked List** added the `prev` pointer that makes mid-list deletion `O(1)` once you hold the node, plus the sentinel pattern that erases null checks at the boundaries; both are load-bearing here. The LRU pattern (one structure for indexing, another for ordering, kept consistent on every operation) is the gateway to a wider family of composite designs covered in later lessons.
Not Started
0%
Skip List
Redis backs its sorted sets with one. LevelDB and RocksDB use one for their in-memory memtables. Java ships a `ConcurrentSkipListMap` in its standard library because lock-free skip lists are dramatically easier to implement than lock-free balanced BSTs. The structure those production systems share is a **Skip List**: a sorted linked list with a few extra express-lane pointers that turn `O(n)` search into `O(log n)` expected. This lesson covers the multi-level structure (a base list with every element, plus higher levels each containing a random subset that acts as a fast-path index), the coin-flip promotion rule that decides how many levels each new node spans, and search, insert, and delete operations whose expected cost is logarithmic without any tree rotations or balance bookkeeping. You will trace the search path that drops one level at a time whenever the next pointer overshoots the target, and you will analyze why a fair coin produces the right level distribution. In **Linked Lists (Singly)**, a search was `O(n)` because the list offered exactly one pointer per node. A skip list keeps that simple node, just adds a small array of forward pointers to higher levels, and lets randomness substitute for the deterministic balancing that AVL and Red-Black trees rely on. Next, **Balanced BST (AVL / Red-Black)** is the deterministic counterpart: same logarithmic guarantees, fundamentally different implementation strategy.
Not Started
0%
Trie (Prefix Tree)
Type the letters `a-p-p` into a search box and the autocomplete dropdown produces `apple`, `application`, `apply`, and `appoint` before you finish the next keystroke. The data structure doing that work is a **Trie** (or prefix tree), where every stored word is a path from root to a marked node and every shared prefix is shared in memory exactly once. This lesson covers the trie node layout (a `children` map plus an `isEndOfWord` flag), `insert`, `search`, and `startsWith` operations that all run in `O(m)` for a query of length `m` (independent of how many words the trie holds), and a `delete` that has to be careful not to break paths used by other words. You will also analyze the space behavior, including when a trie wins over a hash set (prefix queries, lexicographic enumeration) and when it loses (memory-tight workloads with no prefix structure to exploit). In **Hash Map (Dictionary) Basics**, you used hashing to answer 'have I seen this exact key' in `O(1)`; a trie answers a strictly richer question (any prefix lookup) by trading `O(1)` exact-match for `O(m)` traversal. **Trees: Binary Tree Fundamentals** introduced the recursive child-pointer pattern, and a trie generalizes it from two children per node to one child per alphabet symbol. With a trie in your toolkit, the curriculum moves on to graph and hash extensions that solve a different family of problems built on the same node-and-edge thinking.
Not Started
0%
Union-Find (Disjoint Set Union)
Given a million pairwise 'these two accounts belong to the same person' relations, decide whether two arbitrary accounts are now equivalent. Brute-force flood fills are `O(n)` per query; sorting is the wrong shape entirely. **Union-Find** answers each query in nearly `O(1)` amortized time after the relations are merged, with two primitives and a parent array. This lesson covers the disjoint-set abstraction, the `find` operation that walks parent pointers up to a representative, the `union` operation that links two representatives, and the two optimizations (path compression during `find` and union by rank during `union`) that together push the amortized cost to `O(alpha(n))`, where `alpha` is the inverse Ackermann function (effectively constant for any input you can fit in memory). You will trace the parent array as merges happen, and apply the structure to cycle detection in undirected graphs, connected components, equivalence classes, and Kruskal's minimum spanning tree. In **Arrays & Strings**, you saw that an array can encode a mapping from index to value in `O(1)`; a parent array is exactly that mapping, applied to representative pointers. **Graphs: Representation Basics** gave you the vertex-and-edge vocabulary that Union-Find uses to define connectivity, even though the structure itself stores no edges directly. With Union-Find in your toolkit, the curriculum continues with composite designs that combine multiple primitives, starting with the LRU cache pattern.
Not Started
0%
Weighted Graph Representation
Highways have lengths in kilometers, flights have ticket prices in dollars, and network links have latencies in milliseconds. Treating any of those graphs as unweighted throws away the only information that matters for the question you actually care about (the shortest, cheapest, or fastest route), which is exactly the gap a **Weighted Graph** representation closes by attaching a number to every edge. This lesson covers three representations: a weighted adjacency list backed by arrays of `{node, weight}` pairs, a weighted adjacency matrix where `matrix[u][v]` is the edge cost (and infinity for non-edges), and a weighted edge list that stores `(u, v, weight)` triples. You will analyze the space and time trade-offs, see why Dijkstra wants the adjacency list, why Floyd-Warshall wants the matrix, and why Kruskal wants the edge list, and you will represent both directed and undirected weighted graphs correctly in each format. In **Graphs: Representation Basics**, you stored connectivity (whether an edge exists) using the same three shapes; the weighted version simply replaces a boolean or membership check with a numeric value. **Hash Map (Dictionary) Basics** is what makes the adjacency list work: a vertex maps to its neighbor-and-weight list in expected `O(1)`, the same way the unweighted version did. With weights in the picture, the algorithms track unlocks shortest-path and minimum-spanning-tree algorithms that read the weight on every edge during their core inner loop.
Not Started
0%
Algorithms
Binary Search Templates
Standard binary search returns an arbitrary index of a target if duplicates exist, but real problems usually want the _first_ such index, the _last_ such index, or the smallest capacity that ships every package within `D` days. Each variation needs a slightly different loop condition and return value, and getting one wrong produces an off-by-one bug or an infinite loop. **Binary Search Templates** turns those variations into a small set of memorable templates. You will work through first and last occurrence with `<=` versus `<` loop conditions, lower bound and upper bound (the templates behind Python's `bisect_left` and `bisect_right`), binary search on the answer space (the "minimize the maximum" pattern that solves Koko Eating Bananas, Capacity to Ship Packages, and Split Array Largest Sum), and search in rotated sorted arrays where the invariant holds for exactly one half at each step. In **Binary Search (Intro)**, you wrote the canonical exact-match loop and learned why it is `O(log n)`. This lesson keeps the halving idea but switches the question from "is `target` here?" to "what is the smallest index that satisfies a monotonic predicate?". Next, **Linked List Algorithms** turns to pointer manipulation patterns.
Not Started
0%
Bit Manipulation (Intro)
Given an array where every element appears twice except one, find the loner. The hash-map solution is `O(n)` time and `O(n)` space. XOR-ing every element together solves it in `O(n)` time and `O(1)` space, in three lines, exploiting the fact that `a ^ a = 0` and `a ^ 0 = a`. Knowing how integers are laid out as bits unlocks solutions like that across an entire family of problems. **Bit Manipulation (Intro)** covers the building blocks. You will master the six bitwise operators (`&`, `|`, `^`, `~`, `<<`, `>>`) and the standard tricks: check whether `n` is a power of two with `n & (n - 1) == 0`, count set bits, get/set/clear/toggle the ith bit, and the XOR "single number" pattern. The lesson then introduces bitmasks as compact set representations and previews how subset enumeration powers later bitmask DP and TSP algorithms. In **How to Read Code (JS & Python)**, you saw integers and arithmetic. This lesson zooms in past arithmetic: the same integer is also a fixed-width string of bits you can address one at a time. Next, **Divide and Conquer (Intro)** returns to recursion with the recurrence framework that explains merge and quick sort.
Not Started
0%
Divide and Conquer (Intro)
Merge sort and quick sort both run in `O(n log n)`, and once you write down their recurrences (`T(n) = 2T(n/2) + O(n)` and its expected-case sibling) the same `n log n` falls out of both. That is not a coincidence: divide and conquer is a paradigm with a precise mathematical signature, and the Master Theorem reads it directly off the recurrence. **Divide and Conquer (Intro)** introduces the three-step pattern (divide, conquer, combine) and the recurrence-relation toolkit that comes with it. You will analyze merge sort and quick sort as canonical D&C algorithms, look at binary search through the same lens, walk through the divide-and-conquer maximum subarray algorithm, and meet the closest-pair-of-points problem in 1D. Along the way the lesson formalizes the Master Theorem template `T(n) = aT(n/b) + f(n)` and shows you how to read time complexity off it without solving the recurrence by hand. It also draws the line between D&C (independent subproblems) and DP (overlapping subproblems) so you can spot which paradigm fits. In **Recursion Fundamentals**, you saw recursion as one frame calling another. D&C is the case where a frame makes _multiple_ recursive calls and combines their results. Next, **Matrix Algorithms** turns to two-dimensional arrays.
Not Started
0%
Dynamic Programming (Intro)
Naive recursive Fibonacci computes `fib(40)` in seconds, `fib(50)` in minutes, and gives up on `fib(60)`, all because it recomputes the same subproblems exponentially many times. Cache the result of each `fib(k)` the first time you compute it and the same recursion runs in linear time. That single change, remembering answers, is the entire content of dynamic programming. **Dynamic Programming (Intro)** turns that observation into a complete problem-solving framework. You will identify overlapping subproblems and optimal substructure (the two properties a problem must have for DP to apply), and master both approaches: top-down memoization (recursion plus a cache) and bottom-up tabulation (iteratively filling a table). Classic 1D problems include Fibonacci, climbing stairs, coin change, house robber, and a first look at Kadane's algorithm. The lesson teaches you to define state precisely ("what does `dp[i]` represent?"), write the transition ("how does `dp[i]` follow from earlier states?"), set base cases, and apply rolling-variable space optimization that drops `O(n)` to `O(1)`. In **Recursion Fundamentals**, you treated each recursive call as a stack frame. Memoization just attaches a cache so identical inputs return immediately. Next, **Bit Manipulation (Intro)** turns to a different toolkit, where bitwise operators give elegant `O(1)` solutions.
Not Started
0%
Graph Algorithms (Core)
Webpack figures out the order to compile your modules using topological sort. Google Maps figures out the route to your destination using Dijkstra. Your CI system rejects circular imports using cycle detection. The same handful of graph algorithms power an enormous slice of real infrastructure, and almost all of them are short additions to a BFS or DFS skeleton you already wrote. **Graph Algorithms (Core)** covers that handful in detail. You will implement topological sort in two ways (Kahn's BFS-with-in-degree algorithm and the DFS-reverse-postorder algorithm), cycle detection on undirected graphs (DFS with parent tracking) and on directed graphs (DFS with white/gray/black coloring), Dijkstra's shortest-path algorithm with a min-heap and the relaxation invariant that makes it work, connected-component counting via DFS or Union-Find, and bipartite checking via two-color BFS. Along the way you will see why Dijkstra fails on negative edge weights, which motivates Bellman-Ford in the advanced lesson later. In **BFS & DFS (Intro)**, you wrote the two traversal skeletons. **Weighted Graph Representation** gave you the adjacency-list-of-tuples format that Dijkstra and friends actually consume. This lesson is where those primitives turn into named algorithms with clear use cases. From here, **Greedy (Intro)** introduces a different paradigm: instead of exploring every option, commit to the locally best choice at each step.
Not Started
0%
Greedy (Intro)
Given coin denominations of 1, 5, and 25, the greedy "take the largest coin that fits" strategy gives change optimally. Add a coin worth 10 to the system and greedy stays optimal. Replace 25 with 21 and greedy quietly breaks: making 63 cents now wants three 21s, but greedy says one 21 plus two 1s and ten more 1s. The same algorithm, the same input shape, and yet correctness depends entirely on a structural property of the problem. **Greedy (Intro)** explains exactly which property that is. You will learn to test for the greedy-choice property and optimal substructure, the twin ingredients that justify a greedy decision. The lesson covers the canonical problems where greedy provably works (activity selection by earliest end time, fractional knapsack by value-to-weight ratio, job scheduling with deadlines, the jump game, Huffman encoding) and walks through the exchange-argument style of correctness proof. It also shows where greedy fails (0/1 knapsack, coin change with arbitrary denominations) so you know when to reach for DP instead. In **Sorting (Elementary)**, you saw why sorting often costs `O(n log n)`; almost every greedy algorithm starts with a sort step. **Big-O Notation (Upper Bound)** gave you the language to express that cost. Next, **Dynamic Programming (Intro)** picks up where greedy fails, when the local optimum does not guarantee the global one.
Not Started
0%
Linked List Algorithms
Reversing a singly linked list is a four-line iteration with three pointers (`prev`, `curr`, `next`), and yet roughly a third of candidates implement it incorrectly under interview pressure. The reason is that linked-list problems give you no random access: every operation has to be expressed as careful, ordered pointer rewrites, and one missed assignment loses the rest of the list forever. **Linked List Algorithms** is the lesson where pointer manipulation becomes a reliable skill. You will reverse a list iteratively and recursively, then extend the technique to reverse in groups of `k`. You will use Floyd's fast and slow pointers to detect cycles, find the cycle start, locate the middle element, and check whether a list is a palindrome. You will merge two sorted lists, then merge `k` sorted lists with a min-heap. The lesson also covers removing the nth node from the end, finding the intersection of two lists, deep-copying a list with random pointers, and the dummy-node trick that eliminates head-edge cases entirely. In **Linked Lists (Singly)**, you saw how nodes and `next` pointers form a list and why insertion at a known position is `O(1)`. **Two Pointers (Intro)** introduced fast and slow indices on arrays; this lesson reuses the same idea on pointer-linked nodes. Next, **Tree Algorithms** generalizes pointer-and-recursion thinking to branching structures.
Not Started
0%
Matrix Algorithms
Rotating an `n x n` image 90 degrees clockwise sounds like it needs a second matrix to hold the output. The standard trick is two passes over the same matrix: transpose it (swap rows and columns), then reverse each row, and the rotation appears in place with no extra memory. Almost every matrix interview problem hides a similar two-step decomposition under what looks like a hard spatial puzzle. **Matrix Algorithms** trains those decompositions. You will implement spiral, diagonal, snake, and anti-diagonal traversals by managing the four boundary indices that change as the walk continues. You will rotate by 90, 180, and 270 degrees in place. You will search sorted matrices three ways: per-row binary search, the staircase search that runs in `O(m + n)` on row-and-column-sorted matrices, and a single binary search when the whole matrix is sorted. The lesson finishes with in-place transformations like "set matrix zeroes" and Conway's Game of Life that encode state inside the matrix itself. In **Matrix/Grid Fundamentals**, you learned how 2D arrays are laid out and indexed. **Iteration Patterns on Arrays/Strings** taught you single and nested loops in 1D; matrix algorithms layer those patterns across rows and columns with careful boundary management. From here, **Dynamic Programming (Advanced)** revisits 2D structures, this time as DP tables.
Not Started
0%
Sorting (Advanced)
When you call `arr.sort()` in Python or JavaScript, you are running Timsort, an industrial-strength hybrid that switches between merge sort for long runs and insertion sort for short ones. Sorting a billion elements in seconds is possible only because someone, decades ago, broke the `O(n^2)` ceiling that bubble sort, selection sort, and insertion sort all sit beneath. This lesson is where you learn how. **Sorting (Advanced)** covers the comparison-based `O(n log n)` algorithms (merge sort, quick sort, heap sort) and the non-comparison sorts (counting sort, radix sort, bucket sort) that beat that bound under structural assumptions about the data. For each you will trace the divide, sort, combine pattern (or its non-recursive equivalent), analyze best, average, and worst case, examine pivot strategies and partitioning schemes for quick sort, and see why heap sort runs in place. The lesson closes with the `O(n log n)` lower bound for comparison sorting and a quick tour of how built-in sorts (Timsort, V8) blend these techniques. In **Sorting (Elementary)**, you mastered the vocabulary of passes, swaps, invariants, and stability on `O(n^2)` algorithms. **Recursion Fundamentals** gave you the call-stack model that explains the `O(log n)` factor in merge and quick sort. Next, **Binary Search Templates** capitalize on sorted output to solve an entire class of medium-difficulty interview problems.
Not Started
0%
Tree Algorithms
An invert-binary-tree problem famously got Max Howell rejected from Google in 2015, and the joke landed because the canonical solution is three lines of recursion. Trees show up everywhere in interviews precisely because they reward a particular kind of thinking: the answer for a node is almost always a function of the answers for its left and right subtrees, computed recursively, combined at the parent. **Tree Algorithms** trains that decomposition habit across a wide range of problems. You will implement BST insert, search, delete, validation, and the kth-smallest in-order trick. You will compute lowest common ancestor in both a generic binary tree and a BST. You will measure height, diameter, and width, and walk through path-sum problems, root-to-leaf enumeration, and the deceptively tricky maximum-path-sum-between-any-two-nodes. Structural operations include invert, mirror check, flatten to linked list, and serialize and deserialize. The lesson finishes with reconstructing a tree from inorder plus preorder or inorder plus postorder. In **Trees: Binary Tree Fundamentals**, you learned how nodes, children, and the four traversal orders work. **Recursion Fundamentals** gave you the call-stack mental model that every tree algorithm here relies on; tree recursion is essentially recursion with two recursive calls per frame. Next, **Graph Algorithms (Core)** removes the tree assumption (no cycles, no shared nodes) and tackles the more general traversal problems that result.
Not Started
0%
Practice Problems
Accounts Merge
Given a list of accounts where each account has a name and emails, merge accounts that share a common email address.
Design Add and Search Words
Design a data structure that supports adding words and searching for words with wildcard characters, where '.' can match any single letter.
Add Two Numbers
Given two non-empty linked lists representing two non-negative integers in reverse order, add the two numbers and return the sum as a linked list.
Average of Levels in Binary Tree
Given the root of a binary tree, return the average value of the nodes on each level as an array.
Binary Tree Level Order Traversal
Given the root of a binary tree, return the level order traversal of its nodes' values (from left to right, level by level).
Binary Tree Right Side View
Given the root of a binary tree, return the values of the nodes you can see when looking at the tree from the right side, ordered from top to bottom.
Bitwise AND of Numbers Range
Given two integers left and right representing a range [left, right], return the bitwise AND of all numbers in this range, inclusive.
Binary Search Tree Iterator
Implement an iterator over a BST that returns elements in ascending order (in-order traversal).
Binary Tree Zigzag Level Order Traversal
Given the root of a binary tree, return the zigzag level order traversal of its nodes' values (alternating left-to-right and right-to-left for each level).
Car Fleet
Given positions and speeds of cars heading toward a target, determine how many car fleets will arrive at the destination.
Cheapest Flights Within K Stops
Find the cheapest price to fly from a source to a destination with at most k intermediate stops, given a list of flights with prices.
Clone Graph
Given a reference to a node in a connected undirected graph, return a deep copy (clone) of the entire graph.
Coin Change II
Given an array of coin denominations and a target amount, return the number of distinct combinations that make up that amount. Each coin may be used an unlimited number of times.
Coin Change
Given an array of coin denominations and a target amount, return the fewest number of coins needed to make up that amount, or -1 if it cannot be made.
Combination Sum II
Given a collection of candidate numbers (which may contain duplicates) and a target, find all unique combinations where the chosen numbers sum to the target. Each number may only be used once.
Combination Sum
Given an array of distinct integers and a target, return all unique combinations where the chosen numbers sum to the target. Each number may be used an unlimited number of times.
Combinations
Given two integers n and k, return all possible combinations of k numbers chosen from the range [1, n]. Return the answer in any order.
Number of Connected Components
Given n nodes and a list of undirected edges, find the number of connected components in the graph.
Construct BT from Inorder and Postorder
Given inorder and postorder traversal arrays, construct the binary tree and return its root.
Construct BT from Preorder and Inorder
Given preorder and inorder traversal arrays, construct the binary tree and return its root.
Construct Quad Tree
Given an n x n binary matrix, construct a Quad-Tree representation by recursively partitioning the grid into four equal quadrants.
Container With Most Water
Find two lines that together with the x-axis form a container holding the most water.
Copy List with Random Pointer
Create a deep copy of a linked list where each node has a next pointer and a random pointer that can point to any node in the list or null.
Count Good Nodes in Binary Tree
Given a binary tree root, count the number of 'good' nodes where no node on the path from root to that node has a value greater than the node's value.
Course Schedule II
Given courses and prerequisites, return a valid order to take all courses (topological ordering), or an empty array if impossible.
Course Schedule
Given a number of courses and their prerequisites, determine if it is possible to finish all courses (detect if the dependency graph has a cycle).
Daily Temperatures
Given an array of daily temperatures, return how many days you have to wait for a warmer temperature for each day.
Decode Ways
Given a string of digits, determine the total number of ways to decode it, where 'A' = 1, 'B' = 2, ..., 'Z' = 26.
Design Twitter
Design a simplified Twitter with post, follow/unfollow, and a news feed that merges recent tweets from followed users using a heap.
Detect Squares
Design a data structure that supports adding points on a 2D plane and counting the number of ways to form axis-aligned squares with a given query point as one corner.
Edit Distance
Given two strings word1 and word2, return the minimum number of operations (insert, delete, or replace a character) required to convert word1 into word2.
Encode and Decode Strings
Design an algorithm to encode a list of strings into a single string and decode it back, handling any character content.
Evaluate Division
Given equations like a/b = k, answer queries asking for the result of x/y using graph traversal on a weighted directed graph.
Evaluate Reverse Polish Notation
Evaluate the value of an arithmetic expression given in Reverse Polish Notation (postfix), where operators follow their operands.
Factorial Trailing Zeroes
Given an integer n, return the number of trailing zeroes in n! (n factorial). Trailing zeroes are produced by factors of 10, and since 10 = 2 * 5, count the number of times 5 appears as a factor.
Find All Anagrams in a String
Find all start indices where an anagram of pattern p occurs in string s.
Find the Duplicate Number
Given an array of n + 1 integers where each integer is in the range [1, n], find the one duplicate number without modifying the array and using only constant extra space.
Find First and Last Position of Element in Sorted Array
Given a sorted array and a target, find the starting and ending position of the target value in O(log n) time.
Find Minimum in Rotated Sorted Array
Find the minimum element in a sorted array that has been rotated between 1 and n times, using O(log n) time.
Find Peak Element
Find a peak element in an array where the element is strictly greater than its neighbors. Return any peak's index in O(log n) time.
Flatten Binary Tree to Linked List
Given the root of a binary tree, flatten the tree into a linked list in-place using the right pointers in preorder traversal order.
Game of Life
Implement Conway's Game of Life: compute the next state of a board in-place using state-encoding to avoid extra space.
Gas Station
Given arrays of gas available and cost to travel to the next station arranged in a circle, find the starting station index that lets you complete the circuit, or return -1 if impossible.
Generate Parentheses
Given n pairs of parentheses, generate all combinations of well-formed (valid) parentheses.
Graph Valid Tree
Given n nodes and a list of undirected edges, determine if these edges form a valid tree (connected and acyclic).
Group Anagrams
Group an array of strings so that anagrams appear together, using a hash map with sorted-character keys.
H-Index
Compute a researcher's h-index from their citation counts using sorting or counting sort for optimal performance.
Hand of Straights
Given an array of integers and a group size, determine if the array can be rearranged into groups where each group consists of consecutive integers of the given size.
House Robber II
Houses are arranged in a circle. Adjacent houses cannot be robbed on the same night, and the first and last houses are also adjacent. Determine the maximum amount of money you can rob.
House Robber
Given an array representing the amount of money in each house along a street, determine the maximum amount you can rob without robbing two adjacent houses.
Implement Trie (Prefix Tree)
Implement a trie (prefix tree) that supports inserting words, searching for exact words, and checking if any word starts with a given prefix.
Insert Delete GetRandom O(1)
Design a data structure that supports insert, remove, and getRandom in average O(1) time using a hash map paired with a dynamic array.
Insert Interval
Given a set of non-overlapping intervals sorted by start time and a new interval, insert the new interval and merge if necessary.
Integer to Roman
Convert an integer to its Roman numeral representation using a greedy approach with a value-symbol mapping.
Interleaving String
Given three strings s1, s2, and s3, determine whether s3 is formed by interleaving s1 and s2 while preserving the relative order of characters from each string.
IPO
Maximize capital after completing at most k projects by greedily selecting the most profitable affordable projects using a max-heap.
Jump Game II
Given an integer array where each element represents the maximum jump length at that position, find the minimum number of jumps needed to reach the last index.
Jump Game
Given an integer array where each element represents the maximum jump length from that position, determine if you can reach the last index starting from the first index.
K Closest Points to Origin
Find the k closest points to the origin using a max-heap to efficiently track the k smallest distances.
Find K Pairs with Smallest Sums
Given two sorted arrays, find the k pairs with the smallest sums using a min-heap to efficiently explore candidates.
Koko Eating Bananas
Find the minimum eating speed at which Koko can finish all banana piles within h hours, using binary search on the answer.
Kth Largest Element in an Array
Find the kth largest element in an unsorted array using a min-heap or quickselect algorithm.
Kth Smallest Element in a BST
Given the root of a BST and an integer k, return the kth smallest value (1-indexed) using in-order traversal.
Letter Combinations of a Phone Number
Given a string containing digits from 2-9, return all possible letter combinations that the number could represent on a phone keypad.
Longest Common Subsequence
Given two strings, return the length of their longest common subsequence. A subsequence is a sequence that can be derived by deleting some (or no) characters without changing the order of the remaining characters.
Longest Consecutive Sequence
Find the length of the longest consecutive element sequence in an unsorted array in O(n) time using a hash set.
Longest Increasing Subsequence
Given an integer array, return the length of the longest strictly increasing subsequence.
Longest Palindromic Substring
Given a string, return the longest substring that reads the same forwards and backwards.
Longest Repeating Character Replacement
Find the length of the longest substring containing the same letter after performing at most k character replacements.
Longest Substring Without Repeating Characters
Find the length of the longest substring without repeating characters using the sliding window technique.
Lowest Common Ancestor of Binary Tree
Given a binary tree and two nodes, find their lowest common ancestor (the deepest node that is an ancestor of both).
LRU Cache
Design a data structure that follows the Least Recently Used (LRU) cache constraints, supporting get and put operations in O(1) time.
Max Area of Island
Given a binary grid, find the maximum area of an island (connected group of 1s connected 4-directionally).
Maximum Product Subarray
Given an integer array, find the contiguous subarray within the array that has the largest product, and return that product.
Maximum Sum Circular Subarray
Given a circular integer array, find the maximum possible sum of a non-empty subarray that may wrap around the ends of the array.
Maximum Subarray
Given an integer array, find the subarray with the largest sum and return its sum.
Meeting Rooms II
Given an array of meeting time intervals, determine the minimum number of conference rooms required to hold all meetings.
Merge Intervals
Given an array of intervals, merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Merge Triplets to Form Target
Given a 2D array of triplets and a target triplet, determine if the target can be formed by choosing any subset of triplets and taking the element-wise maximum.
Minimum Absolute Difference in BST
Given a BST, find the minimum absolute difference between the values of any two different nodes using in-order traversal.
Minimum Arrows to Burst Balloons
Given balloons represented as horizontal intervals, find the minimum number of vertical arrows needed to burst all balloons.
Min Cost to Connect All Points
Given an array of points on a 2D plane, find the minimum cost to connect all points such that there is a path between every pair, using Manhattan distance as the edge cost.
Minimum Height Trees
Given a tree of n nodes, find all roots that would minimize the tree's height when the tree is rooted at them.
Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element, all in constant time.
Minimum Path Sum
Given an m x n grid filled with non-negative numbers, find a path from the top-left to the bottom-right that minimizes the sum of all numbers along the path.
Minimum Size Subarray Sum
Find the minimal length subarray whose sum is greater than or equal to the target.
Multiply Strings
Given two non-negative integers represented as strings, return their product as a string. You must not convert the inputs to integers directly or use any built-in BigInteger library.
Network Delay Time
Given a network of n nodes and weighted directed edges representing signal travel times, find the time it takes for a signal sent from node k to reach all nodes.
Non-overlapping Intervals
Given an array of intervals, return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.
Number of Islands
Given a 2D grid of '1's (land) and '0's (water), count the number of distinct islands formed by connected land cells.
Number of Provinces
Given an adjacency matrix representing connections between cities, find the total number of provinces (connected components).
Pacific Atlantic Water Flow
Given a matrix of heights, find all cells from which water can flow to both the Pacific and Atlantic oceans.
Palindrome Partitioning
Given a string, partition it such that every substring of the partition is a palindrome. Return all possible palindrome partitions.
Palindromic Substrings
Given a string, return the number of substrings that are palindromes. Each unique start-end position counts as a different substring even if the characters are the same.
Partition Equal Subset Sum
Given an integer array, determine if it can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Partition Labels
Given a string, partition it into as many parts as possible so that each letter appears in at most one part, and return a list of the sizes of these parts.
Partition List
Given the head of a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x, preserving the original relative order.
Path Sum II
Given the root of a binary tree and a target sum, return all root-to-leaf paths where the sum of the values equals the target.
Permutation in String
Given two strings, determine if one string's permutation is a substring of the other.
Permutations
Given an array of distinct integers, return all possible permutations in any order.
Populating Next Right Pointers II
Given a binary tree, populate each node's next pointer to point to its next right node. If there is no next right node, set it to null.
Pow(x, n)
Implement pow(x, n), which calculates x raised to the power n (i.e., x^n). Use binary exponentiation (fast power) to achieve O(log n) time complexity.
Product of Array Except Self
Build an output array where each element is the product of all elements except itself, without using division.
Redundant Connection
Given a graph that started as a tree with one extra edge added, find and return the edge that can be removed to make it a tree again.
Remove Duplicates from Sorted Array II
Remove duplicates from a sorted array in-place so each element appears at most twice, using a two-pointer technique.
Remove Duplicates from Sorted List II
Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
Remove Nth Node From End of List
Given the head of a linked list, remove the nth node from the end of the list and return its head.
Reorder List
Reorder a linked list from L0 -> L1 -> ... -> Ln to L0 -> Ln -> L1 -> Ln-1 -> L2 -> Ln-2 -> ... in-place.
Reverse Integer
Given a signed 32-bit integer, reverse its digits. If the reversed integer overflows the 32-bit signed integer range, return 0.
Reverse Linked List II
Given the head of a singly linked list and two integers left and right, reverse the nodes of the list from position left to position right, and return the reversed list.
Reverse Words in a String
Reverse the order of words in a string, handling leading/trailing spaces and multiple spaces between words.
Roman to Integer
Convert a Roman numeral string to an integer by mapping symbols to values and handling subtractive notation.
Rotate Array
Rotate an array to the right by k steps in-place using the reverse technique for O(1) extra space.
Rotate Image
Rotate an n x n 2D matrix by 90 degrees clockwise in-place, without allocating another matrix.
Rotate List
Given the head of a linked list, rotate the list to the right by k places.
Rotting Oranges
Given a grid where cells contain fresh oranges, rotten oranges, or are empty, determine the minimum time for all fresh oranges to rot via adjacency spreading.
Search a 2D Matrix II
Search for a target value in an m x n matrix where each row and each column is sorted in ascending order, using an efficient staircase approach.
Search a 2D Matrix
Write an efficient algorithm to search for a target value in an m x n matrix where each row is sorted and the first integer of each row is greater than the last integer of the previous row.
Search in Rotated Sorted Array
Search for a target value in a rotated sorted array of unique integers, returning its index or -1 if not found, in O(log n) time.
Set Matrix Zeroes
Given an m x n integer matrix, if an element is 0, set its entire row and column to 0 using constant extra space.
Simplify Path
Given an absolute Unix-style file path, simplify it by resolving '.', '..', and multiple slashes to produce the canonical path.
Single Number II
Given an integer array where every element appears exactly three times except for one element which appears exactly once, find the single element. The solution must use linear time and constant extra space.
Snakes and Ladders
Given a Snakes and Ladders board, find the minimum number of dice rolls to reach the final square from square 1.
Sort Colors
Sort an array containing only 0s, 1s, and 2s in-place using a single pass (Dutch National Flag problem).
Sort List
Given the head of a linked list, sort it in ascending order using O(n log n) time and O(1) or O(log n) space.
Spiral Matrix
Return all elements of an m x n matrix in spiral order, traversing from the outer boundary inward.
Sqrt(x)
Given a non-negative integer x, return the square root of x rounded down to the nearest integer. Use binary search to achieve O(log x) time without using built-in exponent functions.
Best Time to Buy and Sell Stock with Cooldown
Given an array of stock prices, find the maximum profit with unlimited transactions but a mandatory one-day cooldown after each sell.
Best Time to Buy and Sell Stock II
Given an array of daily stock prices, find the maximum profit you can achieve with unlimited buy-sell transactions (one share at a time).
String to Integer (atoi)
Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer. Handle leading whitespace, optional sign, digit parsing, and integer overflow/underflow.
Subarray Sum Equals K
Count the total number of contiguous subarrays whose sum equals k using a prefix sum hash map technique.
Subsets II
Given an integer array that may contain duplicates, return all possible subsets (the power set) without duplicate subsets.
Subsets
Given an integer array of unique elements, return all possible subsets (the power set). The solution set must not contain duplicate subsets.
Sum of Subarray Minimums
Given an array of integers, find the sum of the minimum value of every contiguous subarray, modulo 10^9 + 7.
Sum Root to Leaf Numbers
Given a binary tree where each node contains a digit 0-9, find the total sum of all root-to-leaf numbers.
Sum of Two Integers
Calculate the sum of two integers a and b without using the operators + or -. Use bitwise operations to simulate addition.
Surrounded Regions
Given a board of 'X' and 'O', capture all regions of 'O' that are completely surrounded by 'X' (not touching the border).
Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. You must solve it without modifying the values in the list's nodes.
Target Sum
Given an integer array and a target, assign '+' or '-' to each element and count the number of ways to achieve the target sum.
Task Scheduler
Determine the minimum number of intervals needed to execute all tasks given a cooldown period between identical tasks.
3Sum
Find all unique triplets in an array that sum to zero, avoiding duplicate triplets in the result.
Time Based Key-Value Store
Design a key-value store that can store multiple values for the same key at different timestamps and retrieve the value at a given timestamp using binary search.
Top K Frequent Elements
Find the k most frequent elements in an array using a hash map for counting and bucket sort for efficient selection.
Triangle
Given a triangle array, return the minimum path sum from top to bottom, where at each step you may move to an adjacent number on the row below.
Two Sum II - Input Array Is Sorted
Given a 1-indexed sorted array, find two numbers that add up to a target and return their indices.
Unique Paths II
Given an m x n grid with obstacles, count the number of unique paths from the top-left corner to the bottom-right corner, moving only right or down.
Unique Paths
Given an m x n grid, find the number of unique paths from the top-left corner to the bottom-right corner, moving only right or down.
Valid Parenthesis String
Given a string containing '(', ')' and '*' characters, determine if the string can be valid by treating each '*' as either '(', ')', or an empty string.
Valid Sudoku
Determine if a 9x9 Sudoku board is valid by checking rows, columns, and 3x3 sub-boxes for duplicate digits using hash sets.
Validate Binary Search Tree
Given the root of a binary tree, determine if it is a valid binary search tree using bounds checking or in-order traversal.
Walls and Gates
Given a grid with walls, gates, and empty rooms, fill each empty room with the distance to its nearest gate using multi-source BFS.
Word Break
Given a string and a dictionary of words, determine if the string can be segmented into a space-separated sequence of dictionary words.
Word Search
Given an m x n grid of characters and a string word, determine if the word exists in the grid by following a path of adjacent cells (horizontally or vertically) without reusing any cell.
01 Matrix
Given a binary matrix, find the distance of each cell to the nearest 0 using multi-source BFS.
Zigzag Conversion
Convert a string to a zigzag pattern across a given number of rows, then read it line by line.
System Design
WebSockets, Long Polling & SSE
Standard HTTP is a request-response protocol: the client asks, the server answers. But many modern applications need real-time, bidirectional communication - chat messages, live notifications, stock tickers, collaborative editing, and gaming. This lesson covers three techniques for real-time communication: long polling, Server-Sent Events (SSE), and WebSockets. You will learn how each works, their trade-offs, and when to use which in a system design interview.
gRPC, GraphQL & API Gateway Patterns
REST is the default API style, but it is not always the best fit. gRPC excels at internal microservice communication with its binary protocol, strong typing, and streaming support. GraphQL solves the over-fetching and under-fetching problems of REST by letting clients request exactly the data they need. API Gateways unify multiple backend services behind a single entry point. This lesson covers when and why to use each technology, how they work at a protocol level, and how to combine them in a real-world architecture.
Database Replication (Leader-Follower, Multi-Leader)
Replication keeps copies of your data on multiple servers so you can survive failures, scale reads, and serve users from the nearest region. This lesson covers the three replication topologies (leader-follower, multi-leader, leaderless), the mechanics of synchronous and asynchronous replication, the consistency surprises that come with replication lag, and how to design failover and conflict resolution. By the end you can pick a topology and defend it in an interview, and recognize the bug class behind 'I just wrote it but the read says it does not exist'.
Database Sharding & Partitioning Strategies
Sharding splits a database into many smaller pieces (shards) so writes and storage can scale across servers. The hard part is not the splitting; it is choosing a shard key that avoids hot shards, supporting cross-shard queries, and rebalancing as the data grows. This lesson covers the four sharding strategies, how to pick a shard key, the operational realities of resharding, and when sharding is the wrong answer.
Blob Storage, Object Stores & CDNs
Databases are wrong for storing large unstructured files - photos, videos, backups, logs. Object stores like S3 give you cheap, durable, infinitely scalable storage for blobs, while CDNs cache that content at edges close to users. This lesson covers the object-storage data model, multi-part upload, storage classes, presigned URLs, and how a CDN turns a globally slow origin into a globally fast experience. By the end you can design the media layer for any social, video, or e-commerce system.
Distributed Caching (Redis, Memcached)
A single-node cache eventually runs out of RAM, CPU, or network. Distributed caching spreads keys across many nodes so total capacity and throughput scale horizontally. This lesson covers how Redis and Memcached partition data, replicate it for availability, fail over when nodes die, and how to choose between them. By the end you can design a multi-node cache layer for a real workload, defend the topology in an interview, and recognize the bug class behind 'why is one cache node maxed at 100% CPU while the others are idle?'.
Cache Invalidation Strategies & Consistency
There are only two hard problems in computer science: cache invalidation, naming things, and off-by-one errors. This lesson tackles the first one. We cover TTL-based, write-driven, and event-driven invalidation; the canonical race conditions (lost-update, double-write inconsistency, stale-after-failover); the consistency models a cache can offer; and the patterns that real systems (Facebook, Stripe, AWS) use to keep cached data trustworthy. By the end you can pick an invalidation strategy, defend it under interviewer pressure, and explain exactly why your cache will not silently serve yesterday's data.
Reverse Proxy & API Gateway
A reverse proxy sits at the edge of your infrastructure and terminates client connections so backends never see them directly. An API gateway is a reverse proxy with opinions: authentication, rate limiting, request transformation, and per-route policies. This lesson covers what each does, when one is enough and when you need the other, the canonical features (TLS termination, response caching, request shaping, JWT validation, circuit breaking), and the tools that implement them (NGINX, Envoy, Kong, AWS API Gateway, Apigee). By the end you can place either in a real architecture and articulate the boundary between them in an interview.
Auto-Scaling, Elasticity & Capacity Planning
Auto-scaling lets your fleet grow when traffic surges and shrink when it ebbs, so you pay for the load you actually have. This lesson covers reactive metric-based scaling, predictive (schedule-based) scaling, and the gotchas that turn auto-scaling into auto-outage: warm-up time, scale-down storms, downstream throttling, and cost runaway. We also walk through capacity planning: how to estimate the fleet size you need from QPS, latency targets, and headroom, before relying on the scaler to fix mistakes at 3 a.m. By the end you can configure an auto-scaling policy with confidence and explain to an interviewer why simply 'putting it on auto-scale' is not the actual answer.
Consistency Models (Strong, Eventual, Causal)
Consistency models are the contract between a distributed data store and its clients about what they can and cannot observe. This lesson walks the spectrum from strict serializability at the strong end to eventual consistency at the relaxed end, with stops at linearizability, sequential, causal, read-your-writes, monotonic reads, and monotonic writes. We focus on what each model promises, what bugs it prevents, what it costs in latency and availability, and which production systems implement it. By the end you can name the model your system needs and explain why - the senior-level move that interviewers reward.
Consistent Hashing & Data Distribution
Consistent hashing is the trick that lets distributed caches and databases add or remove nodes without remapping every key in the cluster. This lesson explains why naive `hash(key) % N` is broken, how the hash ring works, why you need virtual nodes to keep load balanced, and how real systems (DynamoDB, Cassandra, Memcached, Discord) implement it. We finish with the modern alternatives (rendezvous hashing, jump consistent hash, Maglev) and the trade-offs that make consistent hashing the answer in interviews 90% of the time.
Message Queues (Kafka, RabbitMQ, SQS)
Message queues let one service hand work to another without waiting, smoothing traffic spikes, decoupling services, and surviving downstream outages. This lesson covers the two queue families (broker-based like RabbitMQ and SQS vs log-based like Kafka), the delivery semantics (at-most-once, at-least-once, exactly-once), the operational essentials (DLQs, consumer groups, backpressure, ordering), and the trade-offs that decide between Kafka, RabbitMQ, and SQS for any given workload. By the end you can pick a queue and defend the choice with the per-property reasoning interviewers reward.
Event-Driven Architecture & Pub/Sub
Event-driven architecture (EDA) is a style where services communicate by emitting and reacting to immutable events instead of calling each other directly. This lesson covers the publish/subscribe pattern, the difference between event notification and event-carried state transfer, the role of an event bus, and how EDA reshapes coupling, scalability, and consistency. We compare it with request/response, walk through real implementations on Kafka, Kinesis, EventBridge, and SNS, and end with the operational pitfalls (event versioning, ordering, schema drift, observability) that bite teams who adopt EDA without preparation.
Fault Tolerance, Redundancy & Failover
Fault tolerance is the property that lets a system keep working when components fail - and at any reasonable scale, components are always failing. This lesson covers the building blocks: redundancy (active-active, active-passive), failure detection (health checks, heartbeats), failover (automatic, manual), and the patterns that make systems gracefully degrade instead of catastrophically crash (circuit breakers, retries with backoff, bulkheads, timeouts). We finish with the operational disciplines that turn architecture into reality: chaos engineering, runbooks, blast-radius analysis, and disaster recovery (RTO/RPO). By the end you can design a system that survives the failure modes interviewers love to throw at you.
Monitoring, Logging, Alerting & SLAs
Observability is what lets you know whether your system is working before customers do. This lesson covers the three pillars (metrics, logs, traces), the SRE-grade definitions of SLI / SLO / SLA, and the operational practices that turn raw telemetry into actionable alerts (RED method, USE method, error budgets, alert fatigue control). We tour the standard production stack (Prometheus, Grafana, OpenTelemetry, ELK, Datadog) and the pitfalls that cause teams to either drown in alerts or miss real incidents. By the end you can design an observability strategy and defend it in an interview against the question 'how would you know if this system was broken?'.
Design Instagram (Photo Sharing)
Design a photo sharing service like Instagram with 500M daily active users uploading 100M photos a day, served as personalized feeds at sub-200 ms p99. The interview centerpiece is the news feed: fan-out on write versus fan-out on read, the celebrity problem, and the hybrid pull-on-read model that real Instagram uses. We also cover photo upload pipelines (presigned URLs, multi-resolution generation, CDN), the metadata data model, and how to scale follow graphs that go from a few friends to hundreds of millions of followers.
Design Twitter / X (Social Feed)
Design a microblogging service like Twitter or X with 250M daily active users posting 500M tweets a day, served as a personalized timeline at sub-200 ms p99. The interview centerpiece is the home timeline: hybrid fan-out at the celebrity boundary, write amplification math, and how Twitter built Manhattan and the Timeline Service to make 250M people see fresh tweets within seconds. We also cover trending topics, the search index, retweet semantics, and how Twitter handles 50,000 tweets per second when a major event happens.
Design Reddit (Forum / Voting)
Design a community-driven forum like Reddit with 50M daily active users, 500K subreddits, and the famous hot/top/best ranking algorithms that decide which posts you see. The interview centerpiece is the ranking system: how to score posts in real time as votes pour in, how to make the front page personalized without per-user fan-out, and how to render nested comment trees at sub-200 ms when a popular thread has 10,000 nested replies. We also cover voting fraud detection, the difference between hot and Wilson score, and the tiered cache that makes 50K reads per second on the front page survive a viral post.
Design YouTube (Video Platform)
Design a video platform like YouTube with 2 billion users, 500 hours of video uploaded every minute, and 1 billion hours watched per day. The interview centerpiece is the video pipeline: chunked uploads, parallel transcoding to 8 resolutions and 3 codecs, HLS/DASH adaptive streaming over a global CDN, and the metadata service that ties it all together. We also cover recommendations (the secondary feed problem), comment scaling, view-counter accuracy, and how YouTube serves 200 Tbps of egress without melting the internet.
Design a Chat System (WhatsApp)
Design a real-time chat system like WhatsApp serving 2B users sending 100B messages per day with sub-second delivery, presence indicators, and read receipts. The interview centerpiece is the persistent WebSocket connection layer: how many connections per server, how to route a message to a recipient who may be on a different server, and how to guarantee delivery when the recipient is offline. We cover the message delivery state machine (sent, delivered, read), the connection routing layer that maps user_id to a chat server, the message store for offline delivery, and presence/typing indicators that operate at a higher write rate than messages themselves.
Design a Notification Service
Design a multi-channel notification service that delivers 10B push, email, and SMS notifications per day across three independent provider networks (APNs, FCM, SendGrid, Twilio) with priority queues, per-user rate limits, and idempotent retries. The interview centerpiece is the fan-out from a single application event to multiple channels and providers, each with its own rate limits, failure modes, and delivery semantics. We cover priority queues for transactional vs marketing traffic, retry policies with exponential backoff, deduplication of duplicate triggers, user preference enforcement, and the device token lifecycle that quietly invalidates tens of millions of tokens per day.
Design an Email Service (Gmail)
Design an email service like Gmail handling 1.8B users storing 500EB of email, accepting ~300B inbound messages per day from the public SMTP network while filtering 90%+ as spam, and serving full-text search over a user's entire inbox in sub-200ms. The interview centerpiece is the asymmetric architecture: SMTP is an untrusted public protocol with hostile traffic patterns (spam, phishing, sender forgery) that needs heavy gateway-side filtering, while the user-facing IMAP/web layer needs cheap reads, pagination of huge mailboxes, and per-user inverted indexes for search. We cover the SMTP MX gateway, the spam pipeline (SPF/DKIM/DMARC + ML), the per-user inverted index for search, and how mailboxes scale when one user holds 50GB of email.
Design Typeahead / Autocomplete
Design a typeahead/autocomplete service like Google Search's suggestion bar that returns the top 10 ranked completions for a query prefix in under 100ms p99, scaling to 5B searches per day with a multi-billion-entry suggestion index. The interview centerpiece is the data structure choice (trie vs sorted strings vs ngram index) and the offline pipeline that ranks suggestions by frequency, recency, personalization, and click-through rate. We cover the trie with precomputed top-K per node, edge n-gram indexes for typo tolerance, the MapReduce/Spark batch pipeline that rebuilds suggestions nightly, and the per-region edge cache that absorbs 99% of traffic.
Design a Web Crawler
Design a distributed web crawler that fetches 5 billion pages per month from the public web while respecting robots.txt, applying per-host politeness limits, deduplicating URLs and content across a 50PB corpus, and feeding the indexer pipeline downstream. The interview centerpiece is the URL frontier: a priority-aware queue of pending URLs sharded by host so politeness rules can be enforced per domain, plus content deduplication via hashing and shingling. We cover the fetcher worker pool, DNS caching, content extraction, the bloom-filter URL seen set, and how to handle hostile sites (large pages, redirect loops, slow responses, deliberate spam).
Design Nearby / Location Service (Yelp)
Design a 'nearby' service like Yelp that returns the top businesses within a search radius of the user's location, ranking by distance, rating, and category, scaling to 200M monthly users querying 100M businesses. The interview centerpiece is the geospatial index: how to find 'all businesses within 5 km of (lat, lng)' efficiently. We compare bounding-box scans, geohashes, quadtrees, R-trees, and PostGIS GIST indexes; we recommend geohash + secondary index for write-heavy systems and quadtree/R-tree for read-heavy. We cover business storage and search, review ranking, the infrequent-update vs frequent-query asymmetry, and how to handle the long tail of remote regions.
Design a Rate Limiter
Design a distributed rate limiter that protects an API platform from abuse and uneven load while staying fast and accurate at 1B requests per day. The interview centerpiece is choosing among the five canonical algorithms (fixed window, sliding window log, sliding window counter, token bucket, leaky bucket) and explaining how to make the chosen one atomic across a Redis cluster. We cover where to place the limiter (edge, gateway, in-process), per-IP vs per-user vs per-API-key keys, returning 429 with Retry-After, the hot key problem, and fail-open vs fail-closed under cache outages.
Design an E-Commerce Platform (Amazon)
Design an Amazon-scale e-commerce platform that lets 200M monthly users browse 100M SKUs, add items to a cart, check out, and have orders fulfilled from regional warehouses. The interview centerpiece is the order lifecycle: how to reserve inventory atomically while a customer is on the checkout page, how to chain cart-to-payment-to-fulfillment as a saga with compensating actions, and how to make checkout idempotent so a flaky network never charges a customer twice. We also cover catalog browse at scale, multi-warehouse fulfillment routing, and the asymmetric read/write workload that makes aggressive catalog caching the right call.
Design a Ticketing System (Ticketmaster)
Design a Ticketmaster-style ticketing platform that sells reserved seats for concerts and sports events, with the central challenge being a flash onsale where 1M users compete for 50K seats in five minutes. The interview centerpiece is the seat reservation lock: each unique seat (Section A, Row 12, Seat 7) cannot be split or sub-bucketed like fungible inventory, so contention is unavoidable. We cover seat-level pessimistic holds with TTL, the virtual waiting room that randomizes queue position to absorb flash demand fairly, anti-bot defenses, dynamic pricing tiers, and the read-replica explosion that interactive seat maps cause.
Design a Key-Value Store (DynamoDB)
Design a Dynamo-style distributed key-value store that scales linearly to thousands of nodes, stays available during partitions, and offers tunable consistency through a quorum (N, W, R). The interview centerpiece is the trio that makes this work at scale: consistent hashing with virtual nodes for partitioning, N/W/R quorums for replication and consistency, and vector clocks for resolving concurrent writes. We cover the gossip protocol for membership, Merkle trees for anti-entropy, hinted handoff for transient failures, sloppy quorum for write availability during partitions, and the LSM-tree storage engine that powers each node.
Design a Distributed Cache (Redis)
Design a Redis-style in-memory distributed cache that serves billions of GET/SET operations per day at sub-millisecond latency, with sharding across hundreds of nodes and explicit eviction when memory fills. The interview centerpiece is the eviction-and-partitioning combination: how LRU and LFU choose what to drop, and how a cluster picks which node owns each key without a central coordinator. We compare client-side hashing, proxy-based partitioning (twemproxy), and Redis Cluster's hash-slot model; we cover cache-aside as the dominant access pattern, replica failover, optional persistence, and the sub-ms latency budget that makes this design fundamentally different from the durable KV store covered in the previous case study.
Design a Content Delivery Network
Design a Cloudflare/Akamai/Fastly-style content delivery network that offloads 95%+ of static traffic from origin servers, brings latency from hundreds of milliseconds down to single digits, and absorbs DDoS attacks at the edge. The interview centerpiece is the cache hierarchy and routing: hundreds of edge POPs anycast-routed to the user's nearest location, a regional shield layer that consolidates fetches, and the origin only seeing the long tail of misses. We cover cache key design with Vary headers, the TTL lifecycle and purge model, stale-while-revalidate for resilience under origin outages, and the moves CDNs make to keep dynamic content fast (programmable edge functions, smart routing).
Design Uber / Lyft (Ride-Sharing)
Design a ride-sharing service like Uber that matches a rider's request to a nearby driver in under 5 seconds, streams driver locations every 4 seconds, computes ETAs, and applies surge pricing in real time at 1M concurrent active drivers and 100K rides/min globally. The interview centerpiece is the dispatch path: how to find the nearest available driver, hold them briefly, and confirm the match without race conditions. We compare geohash, S2, and H3 for the driver index and recommend H3 hex grid for ride-sharing because hex neighbors are equidistant. We cover the trip state machine, surge multipliers per cell, and how location updates fan out without melting the network.
Design Food Delivery (DoorDash)
Design a food delivery service like DoorDash that links three actors (customer, restaurant, courier) with an end-to-end SLA of <40 minutes per order at 10M orders per day across 500K restaurants. The interview centerpiece is the courier dispatch problem, which is fundamentally different from ride-sharing: it is a 3-leg trip (courier-to-restaurant, wait for food, restaurant-to-customer) and the platform routinely batches multiple orders onto one courier to cut cost. We compare Uber's 1:1 matching to DoorDash's many-to-1 batching, design the ETA composition (prep time + assignment time + drive time + handoff), and walk through the order state machine that coordinates three independent humans.
Design a Unique ID Generator
Design a service that generates globally unique, roughly time-sortable 64-bit IDs at 1M IDs per second across hundreds of application servers, without coordination on the hot path. The interview centerpiece is the trade-off between uniqueness, ordering, size, and coordination cost. We compare UUIDv4 (random, no coordination, 128 bits, no ordering), database AUTOINCREMENT (single point of contention), Twitter Snowflake (64 bits, time-ordered, requires worker_id assignment and clock discipline), Instagram's per-shard hybrid, and ULID/KSUID. We deep-dive into Snowflake: bit layout, clock skew handling, leader election for worker IDs, and the dreaded clock-rollback bug.
