Reference shelf
Patterns
Read the problem's signature, reach for the right technique.
The hard part of a problem is rarely the code. It is reading the problem and knowing which tool it is asking for. This page is that translation layer: a signal you can spot, the technique it points to, and why.
How to use this
Scanning arrays and strings
Linear-scan problems where the trick is which indices to move and when, turning a nested-loop brute force into a single pass.
| When you see this | Reach for | Why it fits |
|---|---|---|
| A sorted array and a target pair, or converging from both ends | Two pointers | Sorted order lets one index rise and the other fall, ruling out a whole nested loop in one linear sweep. |
| The best or valid contiguous subarray or substring | Sliding window | A window that grows and shrinks tracks the running answer without re-summing overlap, so a quadratic scan collapses to O(n). |
| A sorted sequence and you need a value, a boundary, or a first-true | Binary search | Order makes half the range irrelevant after every comparison, so a million elements fall in twenty steps. |
| Instant membership, counting, or dedup by key | Hashing | A hash set or map answers 'have I seen this?' in average O(1), replacing a linear search inside the loop. |
Recursion and self-similar problems
Problems that break into smaller copies of themselves. The three techniques differ in whether the pieces are independent, whether they overlap, and whether you want one answer or all of them.
| When you see this | Reach for | Why it fits |
|---|---|---|
| The problem splits into independent halves you can solve and merge | Divide and conquer | Independent subproblems recurse cleanly; the Master Theorem reads the cost straight off the split. |
| Subproblems overlap and an optimal answer builds from optimal sub-answers | Dynamic programming | Overlapping subproblems plus optimal substructure means you can solve each state once and reuse it, cutting exponential recursion to polynomial. |
| You must enumerate or find every valid arrangement under constraints | Backtracking | Choose, explore, un-choose walks the tree of choices, and pruning dead branches early keeps the exponential search tractable. |
The single question that unlocks DP
Making choices and ordering by best
When the problem is a sequence of decisions, the question is whether a greedy local choice is provably safe, or whether you need to keep pulling the current best from a changing pool.
| When you see this | Reach for | Why it fits |
|---|---|---|
| A local choice looks optimal and you can prove it never hurts | Greedy | When the greedy-choice property holds, an exchange argument shows the local pick is part of a global optimum, so you commit without backtracking. |
| You repeatedly need the current smallest or largest of a changing set | Heap / priority queue | A binary heap surfaces the extreme in O(1) and re-settles in O(log n), which beats re-scanning or re-sorting on every step. |
Graph problems
The moment a problem is entities and relationships, it is a graph. What you are asked to find, and whether edges carry weight, picks the traversal.
| When you see this | Reach for | Why it fits |
|---|---|---|
| Fewest steps, level order, or shortest path with equal-weight edges | BFS | A queue explores in rings of increasing distance, so the first time BFS reaches a vertex is along a fewest-edges path. |
| Exhaust paths, detect a cycle, or find connected components | DFS | Following one path to its end before backing up naturally exposes reachability, cycles, and post-order structure. |
| Shortest path in a graph with non-negative weights | Dijkstra | Settling the nearest unsettled vertex and relaxing its edges is greedy-correct exactly when no edge is negative. |
| Shortest path with negative weights, or you must detect a negative cycle | Bellman-Ford | Relaxing every edge V minus 1 times tolerates negative weights, and a further relaxation that still improves proves a negative cycle. |
| Order tasks so every dependency comes first | Topological sort | A DAG's edges define a partial order; a linearization that respects every edge is exactly a valid schedule. |
| Connect all nodes for the least total edge weight | Minimum spanning tree | The cut property makes the cheapest crossing edge always safe, so Kruskal's or Prim's greedily assembles the optimum. |
| Group elements and keep asking whether two are in the same group | Union-find | Disjoint-set with path compression answers dynamic connectivity in near-constant time, far cheaper than re-running a traversal. |
Structure-driven lookups
Sometimes the pattern is not an algorithm but the right container. The access pattern you need points straight at the structure.
| When you see this | Reach for | Why it fits |
|---|---|---|
| Prefix queries, autocomplete, or many words sharing leading characters | Trie | One edge per character indexes shared prefixes, so a prefix lookup costs the key's length, not the dictionary's size. |
| Ordered data with fast insert, delete, and range or successor queries | Balanced BST | A self-balancing tree holds O(log n) on any insertion order while keeping keys sorted for in-order and range walks. |
| A small set of flags or subsets to combine and test fast | Bitmask | Packing booleans into one integer turns set union, intersection, and membership into single-instruction bit operations. |
When two patterns fit