Big O Cheat Sheet
Table of Contents + β
You are halfway through a problem and you wonder, βWait, is a hash table lookup fast or slow? And which sort was the cheap one again?β You know you learned this. You just canβt recall it right now.
That happens to everyone. The thing is, you donβt need to memorize all of it. You need one page you can glance at and find the answer fast. So this tutorial is that page. Itβs a cheat sheet, which just means a short reference you keep nearby to look things up quickly. Bookmark it, and come back whenever your memory goes blank.
π Time Complexities, Fastest to Slowest
First, letβs line up the common time complexities. Time complexity describes how the work an algorithm does grows as the input gets bigger. Smaller growth is better.
Here they are, from the fastest at the top to the slowest at the bottom. As you read down the table, the same algorithm gets slower and slower on big inputs.
| Notation | Name | Example algorithm |
|---|---|---|
| O(1) | Constant | Reading an array element by its index |
| O(log n) | Logarithmic | Binary search on a sorted array |
| O(n) | Linear | Scanning a whole list once |
| O(n log n) | Linearithmic | Merge sort, quick sort (average) |
| O(n^2) | Quadratic | Bubble sort, comparing every pair |
| O(2^n) | Exponential | Naive recursive Fibonacci |
| O(n!) | Factorial | Trying every possible ordering |
So the rule of thumb is simple. O(1) and O(log n) are great. O(n) and O(n log n) are fine for most work. O(n^2) starts to hurt on big inputs. And anything from O(2^n) down is something you avoid unless the input is tiny.
Read the chart top to bottom
The higher an entry sits in this table, the faster it stays as the input grows. When you compare two solutions, pick the one that lands higher up.
ποΈ Data Structure Operations
Now the part people forget most. Each data structure is fast at some things and slow at others. Picking the right one is mostly about knowing these costs.
A quick reminder of the four operations in the table:
- Access means jumping straight to an item by its position.
- Search means looking for an item when you donβt know where it is.
- Insert means adding a new item.
- Delete means removing an item.
These numbers are the average case. That means the cost you usually get in normal use, not the rare worst day.
| Data structure | Access | Search | Insert | Delete |
|---|---|---|---|---|
| Array | O(1) | O(n) | O(n) | O(n) |
| Linked list | O(n) | O(n) | O(1) | O(1) |
| Stack | O(n) | O(n) | O(1) | O(1) |
| Queue | O(n) | O(n) | O(1) | O(1) |
| Hash table | N/A | O(1) | O(1) | O(1) |
A few things worth noticing here:
- An array gives you O(1) access because the computer can jump straight to any index. But inserting or deleting in the middle means shifting everything after it, so thatβs O(n).
- A linked list is the mirror image. There is no jumping to an index, so access is O(n). Adding or removing a node just means relinking pointers, so that part is O(1). But that O(1) only counts if you are already at the spot, like the head or tail. If you first have to walk the list to find the spot, that walking is still O(n).
- A stack and a queue only ever touch one end, so their add and remove are O(1). You are not meant to search inside them, which is why search is O(n).
- A hash table is the star for lookups. It uses a key to compute where the value sits, so search, insert, and delete are all O(1) on average. There is no βaccess by positionβ, which is why access says N/A.
Hash table O(1) is the average, not a promise
On a bad day, when many keys land in the same spot, a hash table operation can slow to O(n). It almost never happens in practice, but that is why we say βaverageβ O(1), not βalwaysβ.
π Sorting Algorithms
Last block, and the one interviewers love to ask about. Each sort has a time cost and a space cost.
- Time is how long the sort takes as the list grows. We list the average and the worst case, because some sorts have a bad worst case.
- Space is how much extra memory the sort needs beyond the list itself. In-place sorts need almost no extra memory, so they are O(1) on space.
| Algorithm | Time (average) | Time (worst) | Space |
|---|---|---|---|
| Bubble sort | O(n^2) | O(n^2) | O(1) |
| Selection sort | O(n^2) | O(n^2) | O(1) |
| Insertion sort | O(n^2) | O(n^2) | O(1) |
| Merge sort | O(n log n) | O(n log n) | O(n) |
| Quick sort | O(n log n) | O(n^2) | O(log n) |
| Heap sort | O(n log n) | O(n log n) | O(1) |
| Counting sort | O(n + k) | O(n + k) | O(k) |
Here is how to read that table in plain words:
- Bubble, selection, and insertion sort are the simple ones. They are easy to write but slow, all O(n^2). They are fine for tiny lists or for learning, not for big data.
- Merge sort is reliably O(n log n) every time, which is great. The catch is it needs O(n) extra memory to merge.
- Quick sort is usually the fastest in practice, also O(n log n) on average. But its worst case drops to O(n^2) when the pivot is chosen badly, so keep that in mind.
- Heap sort gives you a solid O(n log n) and needs almost no extra memory. That makes it a nice balance.
- Counting sort looks magical because it can beat O(n log n). The
kin O(n + k) is the range of the values being sorted. It only wins when that range is small, like sorting ages or exam scores.
Why counting sort uses n + k, not just n
Counting sort counts how many times each value appears, so it has to walk through both the list of size n and the range of size k. When k is small, the total is close to n, which is why it can be so fast.
β¨οΈ Seeing O(1) vs O(n) in Code
The data structure table says array access is O(1) and array search is O(n). It helps to see that with your own eyes. Below, getByIndex jumps straight to a spot, so it never loops. But search walks the list one item at a time until it finds the target.
# O(1): jump straight to the index, no loopdef get_by_index(arr, index): return arr[index]
# O(n): walk the list until we find the targetdef search(arr, target): for i in range(len(arr)): if arr[i] == target: return i # found it return -1 # not found
def main(): arr = [10, 20, 30, 40, 50] print("Element at index 2 (O(1)):", get_by_index(arr, 2)) print("Index of value 40 (O(n)):", search(arr, 40))
if __name__ == "__main__": main()The output of the above code will be:
Element at index 2 (O(1)): 30Index of value 40 (O(n)): 3See the difference? getByIndex has no loop at all, so its cost never changes no matter how big the array gets. That is O(1). search has a loop that can run once for every element, so as the array grows the work grows with it. That is O(n).
π§© What Youβve Learned
You now have a one-glance reference for the costs that show up in almost every problem. Hereβs the recap.
- β Time complexities rank from O(1) and O(log n) at the fast end down to O(2^n) and O(n!) at the slow end.
- β Arrays give O(1) access but O(n) insert and delete; linked lists are the opposite.
- β Stacks and queues add and remove in O(1), and hash tables search, insert, and delete in O(1) on average.
- β Bubble, selection, and insertion sort are O(n^2); merge, quick, and heap sort are O(n log n).
- β Quick sort can drop to O(n^2) in its worst case, and counting sort can beat O(n log n) when the value range is small.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Which time complexity is the fastest as the input grows large?
Why: O(1) means the work stays the same no matter how big the input gets, so it is the fastest.
- 2
What is the average time to access an element by index in an array?
Why: An array can jump straight to any index using its position, so access is O(1).
- 3
Which sorting algorithm has a worst case of O(n^2) even though its average is O(n log n)?
Why: Quick sort averages O(n log n) but drops to O(n^2) when the pivot is chosen badly.
- 4
On average, a hash table search, insert, and delete each cost about how much?
Why: A hash table computes where a key belongs, so those operations are O(1) on average.
π Whatβs Next?
A cheat sheet is for looking things up fast, but you remember it better once you understand where the numbers come from.
- Big O Notation explains what these O(β¦) symbols actually mean and how to read them.
- Time Complexity walks through working out the cost of a piece of code step by step.
Keep this page open while you practice, and these complexities will move from βI have to look it upβ to βI just know itβ.