Lesson 10 of 10
Big-O Notation
"Premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." — Donald Knuth
Every program you have ever written was fast — on your machine, with your test data. Big-O is the language engineers use to answer a harder, more honest question: what happens when the data gets big? It is the single most reliable predictor of whether code that works in a demo will still work when a million people show up — and, not coincidentally, the concept interviewers reach for first.
Your code runs instantly on 100 users. Will it still be standing at 100 million — or will it quietly fall over, and could you have known in advance?
Core Concepts
Big-O describes how the work an algorithm does grows as its input grows. Notice what it is not: it is not seconds, not milliseconds, not "fast" or "slow." A stopwatch measures your laptop on a good day. Big-O measures the shape of the growth — and shape is what betrays you at scale. We write it as O(f(n)), where n is the size of the input and f(n) is roughly how many steps you take.
Two rules turn a messy step-count into a clean Big-O, and they are the two moves interviewers watch for:
- Drop the constants.
O(2n)andO(n)are the same class — doubling the work doesn't change the shape of the curve. So we sayO(n). - Keep only the dominant term.
O(n² + n)becomesO(n²)— asngrows, then²swamps everything else.
That leaves a small family of curves you must know cold. Here is what each one actually costs — the last two columns are why this matters:
| Big-O | Name | Example | n = 10 | n = 1,000,000 |
|---|---|---|---|---|
O(1) |
Constant | Look up a key in a hash map | 1 | 1 |
O(log n) |
Logarithmic | Binary search a sorted array | 3 | 20 |
O(n) |
Linear | Scan a list once | 10 | 1,000,000 |
O(n log n) |
Linearithmic | A good sort (merge / quick) | 33 | ~20 million |
O(n²) |
Quadratic | Compare every pair (nested loop) | 100 | 1,000,000,000,000 |
O(2ⁿ) |
Exponential | Try every subset | 1,024 | a 301,030-digit number |
Read the last column again. At a million items, an O(n) scan is a million steps — a blink. The O(n²) version is a trillion. Same input, same correct answer, and one of them never finishes. That gap is the whole subject.
Seeing it in code
The most common real example — "does this list contain a duplicate?" — written twice. Same output, different shape. Run it, then change the list and run it again:
Click Run to execute the code.
The fast version trades a little space (the set) for a lot of time. That trade — memory for speed — is one of the most important instincts in engineering, and Big-O is how you reason about both sides of it. (Yes: there's also space complexity, measured the same way. The slow version is O(1) space; the fast one is O(n) space.)
One more distinction interviewers love: best, average, and worst case. has_dupe_fast might return on the second item (best case, O(1)) or scan everything (worst case, O(n)). When we say an algorithm "is O(n)" with no qualifier, we almost always mean the worst case — because worst case is what wakes you at 3am.
Finding "Okoro" in a phone book. Reading name by name from page one is O(n) — a million names, up to a million glances. Opening to the middle, deciding "before or after," and repeating is O(log n) — a million names in about 20 glances. Same book, same goal. One approach scales to a city; the other doesn't. Binary search only works because the book is sorted — which is why sorting (an O(n log n) cost, paid once) unlocks fast lookups forever after.
The notation isn't from computer science at all. The German mathematicians Paul Bachmann and Edmund Landau used "big O" in the 1890s to describe how number-theory functions grow. It sat in pure maths for seventy years until Donald Knuth, writing The Art of Computer Programming in the 1960s, borrowed it for algorithms — arguing the field needed a shared, machine-independent way to compare them. That last idea is the gift: Big-O lets you reason about an algorithm without knowing the language, the CPU, or the year. It has outlived every computer it was ever run on.
What experienced engineers actually do with this, day to day:
• They spot the nested loop. Two loops over the same data is the O(n²) smell — the first thing to check when something "gets slow as we grow."
• They reach for a hash map to buy O(1). "Can I remember this instead of re-searching for it?" turns a lot of O(n²) into O(n).
• They know constants still matter in the real world. Big-O ignores them, but an O(n) pass that hits the database on every item can be slower than an O(n log n) one that stays in memory. Big-O tells you the shape; profiling tells you the reality. Pros use both.
The Academy verifies a certificate at /verify/<code>. Naively, you could scan every quiz attempt in the database and compare — O(n) in the number of attempts, getting slower with every student who ever passed. Instead the code is a lookup by primary key: the database's index makes it effectively O(log n), near-instant whether there are 100 certificates or 100 million. Indexes are just sorted phone books your database keeps for you — which is the entire reason the "Indexes" chapter exists later in this Volume.
Common Mistakes
- Confusing Big-O with speed. "
O(1)is always faster thanO(n)" is false for smallnwith big constants. Big-O is about growth, not a stopwatch. - Keeping constants and lower terms. Saying "
O(2n + 5)" in an interview signals you haven't internalised the rules. It'sO(n). - Counting only loops. A single line like
x in a_listis a hiddenO(n)scan. Put it inside a loop and you've builtO(n²)without writing a nested loop. - Forgetting space. Your
O(n)-time fix might quietly useO(n)memory. At scale, memory runs out too. - Optimising the wrong thing. Turning an
O(n)step that runs once intoO(log n)while anO(n²)monster sits next to it. Find the dominant term first.
An O(n²) algorithm handles n = 1,000 in exactly 1 second. Your product succeeds and n grows to 1,000,000 — a thousand times more data. How long does one run take now? Not a thousand seconds. The work grows with the square, so it's a million times more: about 11.6 days. The same success that grew your data by 1,000× grew your runtime by 1,000,000×. That is the moment a startup's "it was fine last month" becomes an outage — and the moment you'll be glad you can see it coming.
Interview Corner
O(n). There's one loop that visits each of the n items once, and the work inside is constant, so the total grows in direct proportion to the input."O(n²). Say why: for each of n items you now do n units of work.O(n log n) the practical limit for comparison sorting, and when would you accept O(n²)?"O(n log n) — that's a proven lower bound. I'd still accept an O(n²) sort like insertion sort for small or nearly-sorted inputs, where its low constant factor and simplicity win. Big-O describes the limit; the real choice depends on n and the data's shape."O(n) for bounded integer keys. Knowing the exception is a senior signal.O(a × b), roughly O(n²), which explains timeouts at scale. The fix trades space for time: put one user's friends in a hash set (O(a)), then scan the other once checking membership in O(1) each — total O(a + b), linear. If it's still hot, move the work off the request path — precompute and cache — because the fastest O(n) is the one you don't run live."- State the Big-O of a function that, for every product in a list, loops through an orders list to count sales. Then rewrite it to be linear using a dictionary of counts — and state the new time and space complexity.
- In the editor above, run
has_dupe_slowandhas_dupe_faston a list of 5,000 numbers and compare. Predict which is faster before you run it. - Out loud (as in a micro1 screen), explain in one breath why doubling the input roughly quadruples an
O(n²)algorithm's work.
Chapter Summary
- Big-O measures how work grows with input size — the shape of the curve, not a stopwatch reading.
- Simplify by dropping constants and keeping the dominant term:
O(2n² + n) → O(n²). - Know the family cold:
O(1),O(log n),O(n),O(n log n),O(n²),O(2ⁿ). - Hash maps buy
O(1)lookups; the classic fix is trading space for time to turnO(n²)intoO(n). - "An algorithm is
O(n)" usually means worst case. Mind space complexity too. - Big-O predicts the cliff before you drive off it — which is why interviews start here.
We now have a language for how algorithms scale. But an algorithm is only as good as the data it runs on — and how you arrange that data decides which complexities are even possible. That's where we turn next: Part II, and the humble building block everything rests on — the Variable.
Editorial reflection — most engineers meet Big-O as a hoop to jump through for interviews, then forget it. That's backwards. The interview asks about it because it's the closest thing our field has to foresight: a way to know, before you ship, whether success will be the thing that breaks you. Learn it as a superpower, and the interview takes care of itself.
Q&A · 0
Enrol to ask questions and join the discussion.
No questions yet — be the first to ask.