Master Complexity Cheatsheet
Complexity is the one thing you’re expected to know cold, without looking it up mid-interview or mid-contest. This page is the single-place reference: every operation, data structure, and algorithm from this track, with its time and space complexity side by side. Treat it as a lookup table, not a lesson — if a row doesn’t make sense, the phase that taught it is linked from context in earlier pages.
What you’ll learn
- The real complexity of every common
listlist/dictdict/setset/dequedeque/heapqheapqoperation — including the ones that silently cost . - Every sorting and searching algorithm from Phase 4, side by side.
- Every data structure’s core operations, from arrays to segment trees, Fenwick trees, and DSU.
- The graph algorithm family — BFS, DFS, Dijkstra, Bellman-Ford, Floyd-Warshall, MST, and topological sort.
- The Big-O growth hierarchy, and a rule of thumb for how large
nncan be under a typical time limit.
Common Python operations
| Operation | listlist | dictdict | setset | dequedeque | heapqheapq |
|---|---|---|---|---|---|
Index / key access x[i]x[i] | avg | — | — | ||
| Append / add | amortized | avg | avg | (heappushheappush) | |
| Append/insert at front | — | — | — | ||
| Pop from end | — | — | — | ||
| Pop from front | — | — | (heappopheappop, smallest only) | ||
| Insert / delete at arbitrary index | avg (del d[k]del d[k]) | avg | not supported directly | ||
Membership test x in ...x in ... | avg | avg | |||
| Search for min/max | (min only, heap[0]heap[0]) | ||||
Sort (sorted(...)sorted(...), .sort().sort()) | on items | on items | (heapify + drain) | ||
sorted(list)sorted(list) from scratch | — | — | — | — | Building via heapifyheapify is |
Sorting algorithms
| Algorithm | Best | Average | Worst | Space | Stable? | Notes |
|---|---|---|---|---|---|---|
Timsort (Python’s sortedsorted/.sort().sort()) | Yes | Adaptive — exploits existing runs of order | ||||
| Merge Sort | Yes | Guaranteed , no worst-case cliff | ||||
| Quick Sort | No | Worst case needs an adversarial/sorted input plus a bad pivot rule | ||||
| Heap Sort | No | In-place, but poor cache locality in practice | ||||
| Insertion Sort | Yes | Best-in-class for nearly-sorted or tiny arrays | ||||
| Selection Sort | No | Always comparisons, minimal writes | ||||
| Bubble Sort | Yes | Teaching tool only — never the right production choice | ||||
| Counting Sort | Yes | kk = range of key values; useless when kk >> nn | ||||
| Radix Sort | Yes | dd = number of digits/passes | ||||
| Bucket Sort | Yes (with a stable inner sort) | Needs a roughly-uniform input distribution |
Searching
| Technique | Time | Space | Requires |
|---|---|---|---|
| Linear search | Nothing | ||
| Binary search (exact match) | Sorted array | ||
lower_boundlower_bound / upper_boundupper_bound (bisectbisect) | Sorted array | ||
| Binary search on the answer | Depends on feasible()feasible() | Monotonic feasibility | |
Hash-based lookup (dictdict/setset) | average, worst | Hashable keys | |
| Two pointers / sliding window | Sorted or monotonic structure |
Core data structures
| Structure | Access | Search | Insert | Delete | Space | Notes |
|---|---|---|---|---|---|---|
Array / Python listlist | worst (end: amortized) | Contiguous, cache-friendly | ||||
| Singly/doubly linked list | at a known node | at a known node | No random access; cheap splicing | |||
Stack (listlist as stack) | (appendappend) | (poppop) | LIFO — both ops at the same end | |||
Queue (collections.dequecollections.deque) | (appendappend) | (popleftpopleft) | FIFO — never use list.pop(0)list.pop(0) here | |||
Hash table (dictdict/setset) | — | avg, worst | avg | avg | Worst case needs adversarial hash collisions | |
Binary heap (heapqheapq) | (min only) | (min) | heapifyheapify builds from scratch in | |||
| Binary Search Tree (unbalanced) | worst | worst | worst | worst | Degenerates to a linked list on sorted input | |
| Balanced BST (AVL / Red-Black) | Guarantees hold even on adversarial input | |||||
| Trie | LL = length of the key/word | |||||
| Segment Tree | query/update | — | update | — | build; lazy propagation keeps range updates | |
| Fenwick Tree (BIT) | query | — | update | — | Simpler and faster in practice than a segment tree for prefix sums | |
| Disjoint Set Union (DSU) | — | findfind | unionunion | — | With path compression + union by rank/size; is the inverse Ackermann function — effectively constant |
Graph algorithms
| Algorithm | Time | Space | Answers |
|---|---|---|---|
| BFS | Shortest path in an unweighted graph, level order, multi-source distance | ||
| DFS | Reachability, cycle detection, topological order, connected components | ||
| Topological sort (Kahn’s or DFS-based) | A valid linear order of a DAG | ||
| Dijkstra (binary heap) | Shortest path, non-negative weights only | ||
| Bellman-Ford | Shortest path with negative weights; also detects negative cycles | ||
| Floyd-Warshall | All-pairs shortest paths, works with negative weights (no negative cycles) | ||
| Prim’s MST (binary heap) | Minimum spanning tree, dense-ish graphs | ||
| Kruskal’s MST (with DSU) | Minimum spanning tree, sparse graphs / edge lists |
The Big-O growth hierarchy
From fastest-growing-slowly to fastest-growing-explosively:
| Complexity | Name | Feels like |
|---|---|---|
| Constant | A dict lookup, an array index | |
| Logarithmic | Binary search, balanced BST operations | |
| Root | Trial-division primality check, sparse tables’ build-adjacent factor | |
| Linear | A single pass — linear search, array sum | |
| Linearithmic | Comparison-based sorting, most divide-and-conquer | |
| Quadratic | Nested loops over the same input — naive pair comparisons | |
| Cubic | Triple-nested loops — Floyd-Warshall, naive matrix multiply | |
| Exponential | Enumerating every subset, unmemoized exponential recursion | |
| Factorial | Enumerating every permutation |
Max nn per time limit — a rule of thumb
Contest judges typically allow roughly - simple operations per
second in Python (often with a looser limit than C++ for exactly this
reason). Working backward from a 1-2 second limit gives a rough ceiling
on nn for each complexity class:
| Complexity | Comfortable max nn |
|---|---|
| -ish | |
| -25 | |
| -500 | |
| -10,000 | |
| - | |
| - | |
| / | up to (the input size barely matters) |
Practice
Self-check — reading a constraint. Given and a 1-second limit, complete the comparison that decides whether an solution fits comfortably.
How to use this cheatsheet
- Treat it as a lookup, not reading material — bookmark it and come back mid-problem when you need to double-check a complexity before committing to an approach.
- When a problem gives you
nnand a time limit, use the “maxnnper time limit” table to shortlist which complexity classes are even in the running before you design an algorithm. - When two data structures both “work,” pick the one whose row here has the better guarantee for the operation your problem calls the most (e.g. a Fenwick tree over a segment tree when you only need prefix sums, not range updates).
Recap
- Python’s built-in containers hide real complexity costs —
list.pop(0)list.pop(0)andlist.insert(0, x)list.insert(0, x)are , not ; usedequedequewhen you need fast operations at both ends. - Timsort’s worst case and best case (on
already-sorted runs) is why
sorted()sorted()/.sort().sort()is almost always the right call over a hand-rolled sort. - Balanced BSTs, Fenwick trees, and segment trees all trade a bit of extra bookkeeping for a guaranteed where a naive structure would degrade to on adversarial input.
- Shortest-path algorithm choice is driven entirely by what the graph allows: unweighted -> BFS, non-negative weights -> Dijkstra, negative weights -> Bellman-Ford, all-pairs on a small graph -> Floyd-Warshall.
- The Big-O hierarchy plus a rough “operations per second” budget is enough to sanity-check almost any algorithm choice before you write a line of code.
Next: Phase 10 — Interview & Contest Strategy, where these templates and complexity guarantees get applied under real time pressure: how to plan an approach, communicate it, and choose the right tool fast when the clock is running.
If this helped you, consider buying me a coffee ☕
Buy me a coffeeWas this page helpful?
Let us know how we did
