input size hint: n up to 1e5–1e6
- constraints
- complexity
Target O(n) or O(n log n) — a nested loop won't pass
Constraints tell you the intended complexity. 1e5 ⇒ n log n; 1e9 ⇒ O(log n) or O(1).
Interview problems tell you what they want. Not in the title — in the phrasing. “Contiguous” is a sliding window. “Fewest steps” is BFS. “Minimum X such that it's feasible” is binary search on the answer. These are the 34 signals the course teaches you to read for, with the reasoning link each time — because the link is what transfers to the problem you haven't seen.
The method behind this table is the first module of the course, and it's free: Reading a Problem: Choosing the Right Tool →
Target O(n) or O(n log n) — a nested loop won't pass
Constraints tell you the intended complexity. 1e5 ⇒ n log n; 1e9 ⇒ O(log n) or O(1).
Write index / in-place array mechanics
A slow write index lags the scan and only advances on elements you keep — dedup, compaction and partitioning are all this one idiom.
Three reversals
Reverse the whole array, then the first k, then the rest — O(n) time and no second array.
Fixed-size frequency array, not a map
A [26]int is stack-allocated, needs no hashing, and is comparable with == so two tables compare in one expression.
Hash map / frequency map
Any time identity or multiplicity matters and order doesn't, a map turns O(n²) scans into O(n).
Hash set (map[T]struct{})
O(1) membership. In Go there's no set type — use map[T]struct{}.
Two pointers
Sortedness lets one pointer move in from each end and discard half the space per step.
Two pointers (fast/slow write index)
A slow write pointer + fast read pointer compacts the array with O(1) extra space.
Sliding window
Contiguous + an optimum means you can grow/shrink a window instead of re-scanning every range.
Prefix sum + hash map
Window breaks with negatives; prefixSum[j]-prefixSum[i]=k, so store seen prefix sums in a map.
Prefix sums / difference array (or a Fenwick tree)
Precompute once, answer each range query in O(1). Difference arrays do the same for range updates.
Binary search (on array or on the answer)
Monotonic predicate ⇒ you can halve the search space. 'Answer' problems are binary search in disguise.
Stack
LIFO = 'the thing I care about is the most recent one I haven't resolved'.
Monotonic stack
Keep the stack sorted; pop while the new element dominates — each element pushed/popped once ⇒ O(n).
Linked list pointer manipulation (dummy head, fast/slow)
No indexing — everything is done by re-wiring `next` pointers with 2–3 cursors.
Recursion / backtracking
Enumerating every combination is a decision per element, which is a recursive tree — choose, recurse, un-choose.
Recursion (define the base case first)
When the shape is self-similar, the code is: base case, recurse on the parts, combine. Getting the base case wrong is the usual bug, not the recursion.
Backtracking
Build a candidate incrementally, abandon (‘prune’) partial candidates that can't succeed.
Tree DFS/BFS recursion
Most tree problems are 'do something at each node + combine children's answers'.
In-order traversal / BST invariant
In-order visits a BST in sorted order — kth smallest, validation, closest value all follow.
Heap / priority queue
You only need the boundary element, not a full sort — a size-k heap is O(n log k).
Min-heap of heads
Always emit the global minimum among the k current fronts — that's exactly a min-heap.
Trie
Shared prefixes are stored once; lookup/insert is O(len), independent of dictionary size.
BFS
BFS explores in layers, so the first time you reach a node is via a shortest path.
DFS (recursion or explicit stack)
DFS naturally follows one path to exhaustion — ideal for reachability and enumeration.
Dijkstra (min-heap)
Greedily settle the closest unsettled node; a priority queue gives you that node in O(log n).
Topological sort (Kahn's BFS or DFS)
A valid order exists iff the dependency graph is acyclic; toposort produces one or detects a cycle.
Union-Find (disjoint set)
Near-O(1) union and find with path compression — beats re-running BFS per query.
Greedy — then prove it, or fall back to DP
Greedy is right only when a local best is never regretted (exchange argument). If it can be, use DP.
Dynamic programming
Optimal substructure + the same subproblem recurring ⇒ memoize or fill a table.
DP over indices (often 2-D)
State = (position in A, position in B); transitions compare/skip one element.
Sort by start, sweep
After sorting, overlap is a local check against the last kept interval / a running end time.
Bitmask (subset enumeration / bitmask DP)
2^20 ≈ 1e6 states fit; an int is a fast, hashable set of up to 64 items.
Bit tricks (XOR, low bit, masks)
XOR cancels pairs; a^a=0. Many O(1)-space tricks come from bit identities.
The other half is turning the pattern into correct code while someone watches. Every module above builds the structure from scratch in Go, steps through it visually, and then hands you exercises with reference solutions and a grading prompt. Reading the problem is module 01; the rest is the course.