Data Structures and Big-O Cheat Sheet for Coding Interviews
β‘ Quick Answer
A practical big O cheat sheet β the complexity ladder with real examples, data structure operation tables, and how to state your complexity in an interview.
Get more content like this on Telegram!
Daily AI tips, notes & resources β free
Advertisement
Data Structures and Big-O Cheat Sheet for Coding Interviews
Big-O describes how an algorithm's cost grows as its input grows. It does not describe how fast your code is.
That distinction is the whole subject. An interviewer asking "what's the complexity?" is asking whether your solution survives a thousand times more data β not whether it runs in eight milliseconds today.
This sheet covers the complexity ladder, the operation tables you look up, and the mapping from problem shape to data structure, which is the part that actually wins interviews.
Updated for 2026.
What Big-O Measures, and What It Ignores
Big-O is an upper bound on growth, with constants and lower-order terms deliberately thrown away.
| Written as | Actual cost | Why |
|---|---|---|
O(n) | 3n + 50 | Constants dropped |
O(nΒ²) | nΒ² + 1000n | Lower-order term dropped |
O(1) | 2 operations or 200 | Both are constant |
Three things Big-O silently ignores, and all three cost you real milliseconds:
Constant factors. An O(n) algorithm with a huge constant loses to an O(n log n) one at every input size you will ever run.
Memory locality. Scanning a contiguous array is dramatically faster per element than following pointers through a linked list, because the CPU cache loads neighbours for free. Both are O(n).
Small inputs. Real sorting libraries fall back to insertion sort β an O(nΒ²) algorithm β for subarrays of a few dozen elements, because its constants are tiny.
What people get wrong: treating Big-O as a benchmark. It is a filter for what scales, not a measurement of what is fast.
The Complexity Ladder
Every complexity you meet in an interview sits somewhere on this ladder. Learn one real example of each rather than the symbol.
| Complexity | Name | n = 1,000 β ops | Real example |
|---|---|---|---|
O(1) | Constant | 1 | Hash map lookup, array index access |
O(log n) | Logarithmic | ~10 | Binary search, balanced BST insert |
O(n) | Linear | 1,000 | Single pass over an array, linked list search |
O(n log n) | Linearithmic | ~10,000 | Merge sort, heap sort, any comparison sort |
O(nΒ²) | Quadratic | 1,000,000 | Nested loop over all pairs, bubble sort |
O(nΒ³) | Cubic | 10βΉ | Naive matrix multiplication, FloydβWarshall |
O(2βΏ) | Exponential | astronomical | Naive recursive Fibonacci, all subsets |
O(n!) | Factorial | worse | All permutations, brute-force travelling salesman |
The practical dividing line is O(n log n). Anything at or below it handles a million elements comfortably. Anything above it does not.
# O(1) β one operation regardless of size
value = my_dict[key]
# O(log n) β halves the search space each step
while lo <= hi:
mid = (lo + hi) // 2
# O(n) β touches each element once
for x in arr: total += x
# O(nΒ²) β every pair
for i in arr:
for j in arr: check(i, j)Each of these does the same abstract job β find or process data β and the loop structure alone tells you the class. Nested loops over the same input multiply; sequential loops add and then collapse to the larger term.
Rules for Reading Complexity Off Code
Sequential loops add, then collapse. O(n) + O(n) is O(2n) is O(n).
Nested loops multiply. A loop inside a loop over the same collection is O(nΒ²).
Different inputs get different letters. Two nested loops over separate arrays is O(nΒ·m), never O(nΒ²).
Halving means log. Any loop that divides the remaining work by a constant factor each step is O(log n).
Recursion costs stack space. A depth-first search recursing n levels deep uses O(n) space even if it allocates nothing.
Complexity Table β Core Data Structures
Average case unless the worst case differs meaningfully, in which case both are shown.
| Structure | Access | Search | Insert | Delete | Space |
|---|---|---|---|---|---|
| Array (static) | O(1) | O(n) | O(n) | O(n) | O(n) |
| Dynamic array | O(1) | O(n) | O(1)* end | O(n) | O(n) |
| Singly linked list | O(n) | O(n) | O(1) at head | O(1) at head | O(n) |
| Doubly linked list | O(n) | O(n) | O(1) given node | O(1) given node | O(n) |
| Stack | O(n) | O(n) | O(1) push | O(1) pop | O(n) |
| Queue | O(n) | O(n) | O(1) enqueue | O(1) dequeue | O(n) |
| Hash map | β | O(1) / O(n) | O(1) / O(n) | O(1) / O(n) | O(n) |
| Hash set | β | O(1) / O(n) | O(1) / O(n) | O(1) / O(n) | O(n) |
| Binary heap | O(1) peek | O(n) | O(log n) | O(log n) pop | O(n) |
| BST (unbalanced) | O(log n) / O(n) | O(log n) / O(n) | O(log n) / O(n) | O(log n) / O(n) | O(n) |
| Balanced BST | O(log n) | O(log n) | O(log n) | O(log n) | O(n) |
| Trie | β | O(k) | O(k) | O(k) | O(alphabet Β· N Β· k) |
* amortised β see the next section. k is the key length for a trie, not the number of stored keys.
The unbalanced BST row is the one people skip. A binary search tree built by inserting already-sorted data degenerates into a linked list, and every operation becomes O(n). Red-black trees and AVL trees exist entirely to prevent that, which is why std::map, Java's TreeMap, and most ordered maps are balanced trees rather than plain BSTs.
Graph Operations
| Operation | Adjacency list | Adjacency matrix |
|---|---|---|
| Storage | O(V + E) | O(VΒ²) |
| Add edge | O(1) | O(1) |
| Check edge exists | O(degree) | O(1) |
| Iterate neighbours | O(degree) | O(V) |
| BFS / DFS | O(V + E) | O(VΒ²) |
Use an adjacency list by default. Interview graphs are almost always sparse, meaning E is far smaller than VΒ², and the list wins on both memory and traversal. Use a matrix only when the graph is dense or you need constant-time edge lookups.
| Algorithm | Time | Notes |
|---|---|---|
| BFS / DFS | O(V + E) | Shortest path in unweighted graphs (BFS) |
| Dijkstra (binary heap) | O((V + E) log V) | No negative weights |
| BellmanβFord | O(V Β· E) | Handles negative weights |
| FloydβWarshall | O(VΒ³) | All pairs, small graphs only |
| Topological sort | O(V + E) | Directed acyclic graphs only |
Sorting Algorithms
| Algorithm | Best | Average | Worst | Space | Stable |
|---|---|---|---|---|---|
| Merge sort | O(n log n) | O(n log n) | O(n log n) | O(n) | Yes |
| Quick sort | O(n log n) | O(n log n) | O(nΒ²) | O(log n) | No |
| Heap sort | O(n log n) | O(n log n) | O(n log n) | O(1) | No |
| Insertion sort | O(n) | O(nΒ²) | O(nΒ²) | O(1) | Yes |
| Counting sort | O(n + k) | O(n + k) | O(n + k) | O(k) | Yes |
Quick sort's worst case is real but rare. It occurs when pivots are consistently terrible, such as always picking the first element of already-sorted input. Randomised or median-of-three pivot selection makes it vanish in practice, which is why quick sort remains the default in most standard libraries despite a worse worst case than merge sort.
Counting sort beats the O(n log n) barrier because it is not a comparison sort. It only works when values are integers in a bounded range k, and it costs O(k) memory β sorting a million values spread over a billion possible keys is a memory disaster.
Which Structure for Which Problem
This is the most useful table on the page. Most coding-interview problems are a lookup in it.
| The problem says⦠| Use | Why |
|---|---|---|
| "Have I seen this before?" | Hash set | O(1) membership |
| "Count occurrences of each X" | Hash map | Key to count in O(1) |
| "Two numbers summing to target" | Hash map | Store complement, one pass |
| "Find duplicates" | Hash set | Insert and check together |
| "Most recent / undo / matching brackets" | Stack | Last in, first out |
| "Process in arrival order" | Queue | First in, first out |
| "Level by level in a tree or grid" | Queue (BFS) | Level order is queue order |
| "Explore all paths / backtracking" | Stack or recursion (DFS) | Depth first is a stack |
| "Top K largest or smallest" | Heap of size K | O(n log k), not O(n log n) |
| "Running median" | Two heaps | Max-heap low half, min-heap high half |
| "Merge K sorted lists" | Min-heap | Always pull the global smallest |
| "Keep data sorted with frequent inserts" | Balanced BST | O(log n) insert and ordered scan |
| "Sorted array, find something" | Binary search | O(log n), no extra structure |
| "Prefix or autocomplete on strings" | Trie | O(k) in key length |
| "Connected components / merge groups" | Union-Find | Near-constant merge and find |
| "Contiguous subarray or substring" | Sliding window | Two indices, O(n) |
| "Sorted array, pair or triplet" | Two pointers | O(n) after sorting |
| "Range sum queries, static array" | Prefix sum array | O(1) per query |
What people get wrong: reaching for a heap when a hash map is the answer, or sorting when a single hash pass would do. If a problem mentions "count", "seen", or "duplicate", the answer is almost always a hash structure.
Space Complexity
Space complexity counts memory that grows with input, not memory you happened to allocate.
| Pattern | Space | Note |
|---|---|---|
| A few variables and pointers | O(1) | Input itself is not counted |
| Hash map with one entry per element | O(n) | The usual cost of a one-pass solution |
| Merge sort's temporary buffers | O(n) | Why heap sort wins on memory |
| Recursion on a balanced tree | O(log n) | Stack depth equals height |
| Recursion on a skewed tree or list | O(n) | The hidden cost people forget |
| 2D dynamic programming table | O(n Β· m) | Often reducible to O(min(n, m)) |
The recursion stack counts. A recursive depth-first traversal allocates nothing explicitly and still uses O(h) space, where h is the height. On a degenerate tree that is O(n), and it is a genuine stack-overflow risk on large inputs.
Most O(nΒ·m) DP tables collapse. If the recurrence only reads the previous row, keep two rows instead of the whole grid and the space drops to O(m). Interviewers love this follow-up.
Amortised vs Worst Case
Two structures on this page have a worst case that almost never happens, and you must be able to explain both.
Dynamic array resize
arr = []
for i in range(n):
arr.append(i) # usually O(1) β occasionally O(n)When the backing buffer fills, the array allocates a larger one (typically double) and copies everything across β an O(n) operation. Because capacity doubles, that copy happens after 1, 2, 4, 8, 16β¦ appends. Summing the copy costs across n appends gives roughly 2n total work, so the amortised cost per append is O(1).
Say it as: amortised O(1), worst case O(n) on the resize.
Hash collisions
A hash map is O(1) because a good hash function spreads keys across buckets evenly. If every key lands in the same bucket, lookup degenerates to scanning a list β O(n).
This is not purely theoretical. It is the basis of hash-flooding denial-of-service attacks, which is why modern runtimes randomise hash seeds per process. Java additionally converts long collision chains into balanced trees, capping the worst case at O(log n) rather than O(n).
Say it as: O(1) average, O(n) worst case with pathological collisions.
How to State Your Complexity in an Interview
Do not announce a symbol. Justify it in one sentence, and always give time and space separately.
Weak: "It's O(n)."
Strong: "Time is O(n log n) β we sort once, then make a single linear pass. Space is O(n) for the hash map, plus O(log n) for the sort's recursion stack."
Three habits that separate strong candidates:
Define your variables. In a graph problem there is no single n. Say O(V + E). In a problem with n strings of length k, say O(n Β· k) β not O(n).
State the worst case when it differs. "Average O(1), worst O(n) if every key collides" shows you know why the structure works.
Name the tradeoff you chose. "I used O(n) extra space to get time down from O(nΒ²) to O(n)" is the sentence that turns a correct answer into a good one.
The Five Mistakes
1. Treating Big-O as a speed measurement. It measures growth. An O(n log n) algorithm regularly beats an O(n) one on real inputs because of constants and cache behaviour. Use Big-O to rule out what cannot scale, then profile.
2. Forgetting recursion stack space. Claiming O(1) space for a recursive solution is wrong. The stack grows with depth, and on a skewed structure that is O(n).
3. Calling hash map lookup unconditionally O(1). It is O(1) average, O(n) worst case. The complete answer takes four extra words and demonstrably separates candidates.
4. Using O(nΒ²) for two nested loops over different inputs. Two separate collections give O(n Β· m). Collapsing them to nΒ² hides the fact that one input may be tiny.
5. Sorting when a hash pass would do. Sorting costs O(n log n). If you only need membership, counting, or complements, a hash structure gets you O(n). Reaching for sort() first is the most common avoidable complexity in interview answers.
Print This Section
LADDER O(1) < O(log n) < O(n) < O(n log n) < O(nΒ²) < O(2βΏ) < O(n!)
practical cutoff for 1M items: O(n log n)
READ sequential loops β add, then keep the larger
nested loops β multiply
halving each step β log n
two inputs β O(nΒ·m), never O(nΒ²)
PICK seen it before / count it β hash set / hash map
last in first out β stack
level by level β queue (BFS)
top K / running extreme β heap
sorted + frequent inserts β balanced BST
prefix on strings β trie
merge groups β union-find
contiguous sub-range β sliding window
CAVEAT dynamic array append amortised O(1), worst O(n)
hash map lookup average O(1), worst O(n)
unbalanced BST O(log n) hoped, O(n) real
SAY IT "Time O(x) because <one reason>. Space O(y) including recursion."Complexity is the language interviewers use to ask whether your solution survives growth. Learn the ladder and the structure-to-problem mapping, and most of the rest is arithmetic you can do out loud.
π Next in this collection: 15 Coding Interview Patterns That Solve Most Problems, or return to The Complete Developer Cheat Sheet Collection.
Advertisement
π¬ DiscussionPowered by GitHub Discussions
Frequently Asked Questions

AI & Software Engineering Editorial Team
The AiTechWorlds editorial team writes and reviews in-depth guides on artificial intelligence, machine learning, prompt engineering, programming, and developer tools. Every article is fact-checked against primary sources and kept up to date for working developers and CS students.
Not sure yet? Ask AI about this article
Get an instant, unbiased AI summary of βData Structures and Big-O Cheat Sheet for Coding Interviewsβ.
Advertisement
Related Articles
Bash Scripting Cheat Sheet (The First Line Every Script Needs)
A practical Bash scripting cheat sheet β variables, conditionals, loops, functions, and the set -euo pipefail line that turns silent failure into loud failure.
15 Coding Interview Patterns That Solve Most Problems
The 15 coding interview patterns that cover most problems β the signal that identifies each one, a minimal code skeleton, and a two-minute recognition table.
CSS and Tailwind Cheat Sheet: Flexbox, Grid and Centering Solved
A practical CSS and Tailwind cheat sheet β Flexbox vs Grid decision rules, every centering method, responsive breakpoints, and the specificity traps.
The Complete Developer Cheat Sheet Collection: 20 References Worth Saving
Twenty programming cheat sheets every developer should save β Python, Git, SQL, Docker, system design and more, with what to memorise and what to look up.