JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Why Speed Matters: Big-O, Gently

How do we say one algorithm is "faster" without timing it on a stopwatch? We count **steps**, not seconds, and watch how that count *grows* as the input gets bigger. That single idea — captured by **Big-O** — lets you compare recipes on a napkin, before writing a line of code.

Count steps, not seconds

Your first instinct might be to time an algorithm with a stopwatch. But seconds lie. The same code runs faster on a newer laptop, slower when other apps are open, faster after a warm-up. Timing tells you about *your machine today*, not about the algorithm itself. So we measure something the hardware can't change: the *number of basic steps* the algorithm performs — a comparison, an addition, a swap. That count is the honest fingerprint of how much work the recipe really does.

But step counts depend on input size, so we ask the sharper question: as the input grows, how does the work grow *with* it? Double the data — does the work double, stay flat, or explode? That relationship between input size (we call it *n*) and number of steps is the algorithm's [[time-complexity|time complexity]], and watching it as *n* heads toward huge is called [[asymptotic-analysis|asymptotic analysis]]. Small inputs are fast no matter what; it's the big ones that separate a good algorithm from a disaster.

Big-O: keep only the shape that matters

[[big-o-notation|Big-O notation]] is a tidy way to write that growth shape. We don't care about the exact step count — `3n + 7` and `n` grow the same way as *n* gets big — so Big-O throws away two kinds of clutter. Drop the constant multipliers: `5n` becomes O(n). Drop the lower-order terms: `n² + 100n + 9` becomes O(n²), because for large *n* the `n²` part dwarfs everything else. What's left is the pure *shape* of the growth — and that's exactly what survives no matter whose computer runs it.

Here are the few shapes you'll meet over and over, from best to worst. Read O(1) as "constant", O(log n) as "logarithmic", O(n) as "linear", O(n log n) as "linearithmic", and O(n²) as "quadratic".

approx. steps as n grows (lower is better):

  n          O(1)   O(log n)   O(n)        O(n log n)     O(n^2)
  ----------------------------------------------------------------
  10          1       ~3        10            ~33            100
  100         1       ~7       100           ~664         10,000
  1,000       1      ~10     1,000        ~9,966      1,000,000
  1,000,000   1      ~20  1,000,000  ~19,931,569  1,000,000,000,000

  O(1)  flat        O(log n)  barely grows    O(n)  keeps pace
  O(n log n) gentle climb     O(n^2)  blows up fast
Same n, wildly different work. O(1) never moves; O(log n) crawls; O(n) tracks n; O(n²) reaches a *trillion* steps at a million items — the gap is the whole reason we study this.

Reading Big-O off your own code

You can often spot the shape just by looking. A handful of plain statements with no loop is O(1) — the work doesn't depend on *n* at all. One loop that runs through the data once is O(n). A loop *inside* another loop, each going over the data, is O(n²) — because for each of n items you do n more steps. And anything that *halves* the problem each time (you'll see this in binary search) is O(log n). Watch the loops, and the shape usually announces itself.

int first = v[0];                 // O(1): one step, ignores n

for (int i = 0; i < n; i++)        // O(n): one pass over the data
    sum += v[i];

for (int i = 0; i < n; i++)        // O(n^2): a loop inside a loop
    for (int j = 0; j < n; j++)    //   n items x n steps each
        if (v[i] == v[j]) found++;
Three snippets, three shapes. No loop -> O(1). One loop over n -> O(n). A loop nested in a loop, each over n -> O(n²).