Learn DSA

A structured path through data structures and algorithms. The articles build on each other, so follow the order if you're starting fresh — or jump to whatever you want to brush up on. Most posts include interactive visualizations you can step through.

Practice: pattern-wise questions

Curated LeetCode and GFG questions grouped by pattern — each one explained with examples, multiple approaches, and a dry run.

Track your progress — everything you have marked complete, by pattern and difficulty.→

0 of 39 articles read

Progress is saved in your browser.

1

Foundations

How to reason about running time, recursion, and the two search/sort ideas everything else builds on.

  1. Start here — the call stack model explains how every recursive algorithm in later phases actually runs.

  2. Bubble, insertion, and merge sort as a first tour of comparing algorithms by their complexity.

  3. The halve-the-problem idea, first over arrays and then as a tree structure.

  4. AND, OR, XOR, and shifts — a small toolbox that keeps reappearing in hashing and optimization tricks.

2

Core data structures

The structures behind almost every practical program — and most interview questions.

  1. How a sequence sits in memory — the trade-off between instant access and cheap inserts that every later structure inherits.

  2. Pointer manipulation basics plus the classic fast/slow-pointer cycle trick.

  3. Turning any key into a number — the idea a hash map is built on, and why collisions can never be fully avoided.

  4. What actually makes lookups O(1): hashing, buckets, collisions, and resizing.

  5. The array-backed tree that always knows its minimum — the engine behind schedulers and top-K problems.

  6. A heap-driven greedy algorithm with a proof: merge the two rarest symbols, and get the optimal prefix code behind gzip and PNG.

  7. A tree keyed by characters instead of comparisons; the structure behind autocomplete.

3

Algorithmic patterns

Reusable solution shapes — recognizing the pattern is most of the work in solving a new problem.

  1. The pattern that turns a whole family of O(n²) array and string problems into O(n).

  2. Expand around each of the 2n − 1 centres: a simple O(n²) answer with O(1) memory, and when DP or Manacher fits better.

  3. Precompute once, answer range queries with a subtraction — the cheapest big win in array problems.

  4. Binary search without a sorted array: search the range of possible answers, using a yes/no check that flips exactly once.

  5. A stack that stays ordered, and the four "nearest greater/smaller element" questions it answers in O(n).

  6. The monotonic stack with a moving left edge: a deque that gives every window's maximum in O(n).

  7. Divide-and-conquer and heap ideas applied back to sorting — partitioning shows up far beyond sort itself.

  8. Partition once, keep only the side with the answer — the kth smallest element in expected O(n).

  9. A heap holding one candidate per sorted list — the pattern behind external sorting and merging k lists in O(N log k).

  10. BFS and DFS are the entry point to every graph problem: reachability, shortest paths, cycles.

  11. Grids are graphs in disguise: BFS from every unvisited land cell counts islands — and solves a whole family of grid problems.

  12. BFS with two alternating colours: split a graph into two sides, or find the odd cycle that makes it impossible.

  13. The same problem solved twice — an O(n²) dynamic program, then the O(n log n) version built on a binary search.

  14. Overlapping subproblems, memoization, and tabulation — the pattern people find hardest, made mechanical.

  15. The classic "choose a subset under a budget" DP — a two-dimensional table, then the one-array version that iterates backwards.

  16. A two-string DP table, the walk back that recovers the answer, and how the same idea produces the diffs in code review.

  17. When the state must remember a set: encode it as bits, and n ≤ 20 problems become 2ⁿ·n states instead of n! orders.

4

Putting it together

Problems that combine several structures at once — the shape real systems (and hard interviews) take.

  1. A hash map and a doubly linked list working together for O(1) everything — a capstone for phases 1–3.

  2. Systematic search over choice trees: permutations, subsets, and constraint problems.

  3. Near-constant-time connectivity queries, and the trick behind Kruskal’s algorithm.

  4. Prefix sums that survive updates — the same range queries in O(log n), built out of one bit trick.

  5. Kruskal and Prim: union-find and priority queues applied to the cheapest way to connect everything.

  6. Weighted graphs — where BFS stops working and priority queues take over.

  7. Where Dijkstra’s greedy step breaks: negative edge weights, and detecting negative cycles.

  8. Dijkstra plus a heuristic: the same loop, guided toward the goal, and the conditions that keep it optimal.

  9. Two depth-first passes find every group of nodes that can all reach each other — and turn any directed graph into a DAG.

  10. Precompute ancestors at powers of two, and any tree query — LCA, k-th ancestor, distance — takes O(log n) jumps.

  11. Augmenting paths by BFS, residual edges that undo earlier choices, and the min cut that falls out — plus matching problems that reduce to it.