A pattern is a compact description of the state that removes repeated work. “Contiguous and longest” suggests a window because the useful state has two moving boundaries. “Minimum steps with unweighted edges” suggests BFS because the queue processes vertices in nondecreasing distance. The chapter links below explain that connection, establish the invariant, and then implement it in C++.
Write the direct solution, name what it rescans, and identify the state that can preserve the answer.
Say what is true before and after every iteration. Pointer movement and data-structure updates follow from it.
Empty, singleton, duplicate, impossible, disconnected, overflow, and maximum-size cases expose most defects.
Chapters
Two pointers, sliding windows, prefix state, hashing, cyclic placement, intervals, and fast/slow traversal.
Chapter 2 · 9 patterns Trees and graphsDFS, BFS, topological order, disjoint sets, shortest paths, MSTs, low-link values, and components.
Chapter 3 · 7 patterns Search, selection, and ordered stateBoundary binary search, feasibility search, heaps, running medians, monotonic structures, and tries.
Chapter 4 · 8 state shapes Recursion, backtracking, and DPChoose/recurse/undo, memoization, linear state, knapsack, two-sequence grids, and interval DP.
Chapter 5 · 6 structures Range queries and coordinate stateCompression, Fenwick trees, order statistics, iterative and lazy segment trees, and sparse tables.
Chapter 6 · 9 tools Strings, bits, and mathematicsKMP, Z, double rolling hash, Manacher, XOR identities, modular exponentiation, sieves, and combinations.
Chapter 7 · 7 patterns Greedy orderings and game statesExchange arguments, deadline heaps, inversion counting, permutation cycles, Nim, and Sprague–Grundy.
Executable companion Tested C++20 sourceStrict warnings, fixed edge cases, ASan/UBSan, and 4,000 deterministic differential comparisons.
Recognition map
Use the statement and constraints to narrow the candidates. The signal is not a proof. It tells you which invariant to test against the examples and constraints.
| Statement or constraint | State to try | Representative problems |
|---|---|---|
| Sorted sequence with a pair, triplet, or boundary query | Two pointers | Two Sum II, 3Sum, palindrome, container area |
| Longest or shortest contiguous region | Sliding window | Longest unique substring, minimum window, replacement |
| Count subarrays with a target aggregate | Prefix state + hash counts | Subarray Sum Equals K, Contiguous Array, range sums |
| Values belong at indices 0…n−1 or 1…n | Cyclic placement | First missing positive, disappeared numbers, duplicates |
| Pairs of start/end coordinates | Sort and sweep | Merge/insert intervals, rooms, overlap removal |
| A “next” function may revisit a state | Fast and slow pointers | Linked-list cycle, duplicate number, happy number |
| Path, component, subtree aggregate, exhaustive reachability | DFS | Islands, tree diameter, path sum, clone graph |
| Minimum edges or steps when every edge has equal cost | BFS | Word ladder, rotting oranges, level order |
| Prerequisites or “must happen before” | Topological order | Course schedule, build order, alien alphabet |
| Groups merge and connectivity is queried repeatedly | Disjoint set | Redundant edge, accounts merge, Kruskal |
| Nonnegative weighted shortest path | Dijkstra | Network delay, cheapest route, path effort variants |
| Negative edges or all-pairs distances | Bellman–Ford or Floyd–Warshall | Negative cycles, city thresholds, transitive costs |
| First valid index or monotone feasibility | Binary search | Lower bound, rotated search, shipping capacity, Koko |
| Largest/smallest k without fully sorting | Bounded heap | Top K frequent, closest points, merge k lists |
| Nearest greater/smaller boundary | Monotonic stack | Temperatures, histogram, next greater |
| Window extremum while endpoints advance | Monotonic deque | Sliding maximum, constrained DP transitions |
| Prefix lookup over many strings | Trie | Autocomplete, word board, prefix replacement |
| Generate all valid configurations | Backtracking | Subsets, permutations, N-Queens, word search |
| Count ways, minimum cost, or maximum value with overlap | Dynamic programming | Robber, coin change, partition, edit distance |
| Dynamic prefix sums or ranks | Fenwick tree | Inversions, count smaller, order statistics |
| Dynamic arbitrary range aggregate | Segment tree | Range max/sum, bounded-value LIS transitions |
| Many static range min/max/gcd queries | Sparse table | Range minimum and lowest common ancestor reductions |
| Borders, periods, or exact substring matches | KMP prefix function | Repeated substring, prefix occurrence, pattern search |
| Prefix match length at every position | Z function | Pattern occurrences, string overlap, prefix comparisons |
| Static substring equality or length feasibility | Double rolling hash | Repeated substring, longest common substring |
| All palindrome radii | Manacher | Longest/count palindromic substrings |
| Maximize count/value after sorting by a key | Greedy + exchange argument | Interval scheduling, deadlines, fractional choices |
| Two players alternate over independent components | Nim or Grundy values | Pile games, subtraction games, split components |
From direct solution to maintained state
- Read constraints first. A quadratic loop can be correct for
n ≤ 2,000and impossible forn = 200,000. - Write the direct operation count. “For each right endpoint, I scan every earlier value” is more useful than only writing
O(n²). - Name the repeated query. Examples: “Have I seen this complement?”, “What is the largest live value?”, or “Which prefixes differ by k?”
- Choose state supporting that query. Hash table, deque, heap, bitset, tree, or DP table.
- State the invariant before implementation. Every movement or update must restore it.
- Count how often each item changes state. This establishes the actual complexity of windows, stacks, deques, and amortized structures.
- Test the direct and optimized versions together. Randomized differential tests are especially effective for prefix counts, trees, and range structures.
C++ mechanics that affect otherwise-correct algorithms
Promote before arithmetic
Casting after a signed overflow does not repair it. At least one operand must be widened before the operation.
wide_arithmetic.cpplong long product = 1LL * left * right;
long long distance = static_cast<long long>(a) + b;
int middle = low + (high - low) / 2;Use half-open ranges consistently
The chapters use [begin, end). Length is
end - begin, an empty range has equal endpoints, and
adjacent ranges compose without adding or subtracting one.
half_open.cpplong long range_sum(
const std::vector<long long>& prefix,
std::size_t begin,
std::size_t end
) {
return prefix[end] - prefix[begin];
}Fast input without mixed buffering
For input-heavy programs, detach C++ streams from the C stdio
buffers and stop flushing cout before each read. After
doing this, keep all input on cin. Do not mix it with
scanf.
io_setup.cpp#include <iostream>
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int count;
std::cin >> count;
// Use '\n' for ordinary line endings; std::endl also flushes.
}The repository package compiles with C++20, strict conversion and shadowing warnings, and no test framework. It runs fixed edge cases plus 4,000 deterministic comparisons against direct implementations. See examples/cpp-patterns.