What Big-O measures
Imagine finding a friend’s number in a printed phone book with a million names:
- Read every page from the start: in the worst case, a million looks. Double the book, double the work. That’s O(n), “linear”.
- Open in the middle, then the middle of the half that’s left, and so on: about 20 looks for a million names, 21 for two million. That’s O(log n), “logarithmic”.
- Speed dial: one tap, no matter how many names. That’s O(1), “constant”.
Big-O doesn’t count seconds, because those depend on the phone and the reader. It describes how the amount of work grows when the input grows. n is the size of the input: the number of names, items in a list, characters in a string.
Big-O gives an asymptotic upper bound on growth: f(n) is O(g(n)) if f(n) ≤ c·g(n) for all n beyond some n₀. In interviews it usually means the worst case unless you say otherwise, and you’re expected to state time and space separately, to distinguish worst, average and amortized costs (hash maps, dynamic arrays), and to name every variable that matters (O(n·m), O(V + E)).
The useful part in practice is knowing the hidden costs of library calls in each language, and knowing when Big-O stops being the deciding factor: small n, constant factors and memory locality. Both are in the Detailed version.
The complexities you’ll meet
| Big-O | Name | Example | Steps for n = 1,000,000 |
|---|---|---|---|
| O(1) | constant | read array[i], look up a key in a hash map | 1 |
| O(log n) | logarithmic | binary search in a sorted array | ~20 |
| O(n) | linear | one loop over the array | 1,000,000 |
| O(n log n) | linearithmic | sorting | ~20,000,000 |
| O(n²) | quadratic | comparing every pair | 1,000,000,000,000 |
| O(2ⁿ) | exponential | trying every subset | more than atoms in the universe |
At a billion simple steps per second, O(n log n) finishes in 0.02 seconds and O(n²) in about 17 minutes. That gap is why interviewers care.
Counting halvings
Logarithms sound scary, but in code they almost always mean “the problem gets cut in half each step”:
Predict the output
What gets printed for n = 8?
var remaining = 8
var steps = 0
while remaining > 1 {
remaining /= 2
steps += 1
}
print(steps)var remaining = 8
var steps = 0
while (remaining > 1) {
remaining /= 2
steps++
}
println(steps)int remaining = 8;
int steps = 0;
while (remaining > 1) {
remaining /= 2;
steps++;
}
System.out.println(steps);let remaining = 8;
let steps = 0;
while (remaining > 1) {
remaining = Math.floor(remaining / 2); // / alone would give fractions
steps++;
}
console.log(steps);8 → 4 → 2 → 1: three halvings, and the loop stops when remaining reaches 1. In general the answer is log₂(n), rounded down: 20 for a million, 30 for a billion. That's why O(log n) algorithms barely notice how big the input is.
Beyond Big-O
Big-O is the first filter, not the final answer:
- Constants and locality. Iterating an array is several times faster than a linked list of the same length, both O(n), because arrays are contiguous and CPU caches prefetch them. A sorted
Arraywith binary search often beats aHashMapfor a few hundred elements. - Small n. Insertion sort beats O(n log n) sorts on a few dozen elements, which is why real sort implementations (TimSort on the JVM and in V8, a TimSort variant in Swift) use it for small runs.
- Name every input. O(n + m) and O(n·m) matter when one input is small (a 5-item cart against a 1-million-item catalog).
- Size vs value. An algorithm that loops up to the value of a number (
for i in 0..<amount) is exponential in the number of digits: “pseudo-polynomial”. It matters for problems like coin change with huge amounts. - The real bottleneck. One extra network round trip or database query per item (the N+1 problem) costs more than any in-memory O(n²) on a few thousand items.
- State time and space separately; say worst, average or amortized; name every input (O(n·m) vs O(n + m), O(V + E)).
- Big-O is a filter: constants, memory locality, small n and I/O round trips (N+1 queries) often decide real performance. Looping up to a number’s value is pseudo-polynomial.
Check this part
What does Big-O describe?
Binary search halves the remaining range each step. About how many steps for 1,000,000 items?
Both are O(n). Why is iterating an array usually much faster than a linked list?
A 5-item cart is checked against a 1,000,000-item catalog: for each cart item, a hash lookup. How do you state the complexity?