A quick reference for choosing a pattern, recalling its Python template, and checking the edge cases.
Big-O & the Python Toolkit
Read n, pick a target complexity, and choose the built-in that gets you there without a hidden O(n) loop.
Arrays & Hashing
Spend O(n) memory on a set or dict so every "have I seen it?" costs O(1).
Two Pointers
Two indices that only ever move one way turn an O(nยฒ) pair search into a single O(n) pass.
Sliding Window
Contiguous subarray/substring + a rule: grow right, shrink left, each index enters and leaves once. O(n).
Prefix Sums
Precompute running totals once; any range sum is P[r + 1] - P[l].
Stacks & Monotonic Stacks
Push what's still unresolved; the newest item is resolved first. Keep the stack monotonic to answer 'next greater/smaller' in O(n).
Binary Search
Turn the question into a predicate that flips once (F F F T T T), then halve the range until lo == hi.
Linked Lists
Hold pointers, not indexes: rewire `next` in place, use a dummy head for edge cases, and two runners for middles, cycles and gaps.
Trees: DFS & BFS
Each call answers one question about one subtree: base case on None, trust the children, combine.
Heaps & Top-K
Need the min/max over and over while data changes? A heap gives it in O(1) and updates in O(log n).
Backtracking
Build answers one choice at a time: choose, explore, un-choose, and prune branches that can't work.
Graphs
Nodes + connections: build an adjacency list, then traverse (DFS/BFS), order (Kahn), group (unionโfind) or weigh (Dijkstra).
Dynamic Programming
Define a state, write how it's built from smaller states, seed the base cases, and compute each state once.
Greedy & Intervals
Make the locally best move (usually after sorting), and make sure an exchange argument says it never hurts.
Tries & Bit Manipulation
Tries answer prefix questions in O(word length); bit tricks turn pairs, parity and subsets into O(1) integer ops.