# It's About How Things GROW

Here's the thing nobody says out loud when they teach this: Big-O is not about how *fast* your code is.
It doesn't measure seconds. It doesn't know what computer you're on. It can't tell you whether your
program finishes in 2 milliseconds or 2 minutes.

What it *does* tell you is something more useful: **as your input gets bigger, how does the amount of
work grow?** That distinction is the whole game. Once it clicks, the notation stops being scary,
because the notation is just a shorthand for an answer you can reason out yourself.

## The one question to keep asking

Whenever you look at a piece of code, ask:

> **If I double the size of the input, what happens to the work?**

That's the question Big-O answers. There are only a few possible answers, and they're all things you
already understand from real life:

- **The work barely changes.** Doubling the data makes almost no difference. (Looking up one word in a
  dictionary doesn't get harder when the dictionary gets thicker - you flip near where it should be.)
- **The work doubles too.** Twice the data, twice the work. Fair and predictable. (Reading every page
  of a book: twice as many pages, twice as long.)
- **The work *squares*.** Twice the data, *four* times the work. This is the one that quietly ruins
  your afternoon. (Everyone at a party shaking hands with everyone else: invite twice as many people
  and you get roughly four times as many handshakes.)

Big-O is just a tidy label for which of these is happening. `O(n)` means "doubles." `O(n²)` means
"squares." `O(1)` means "barely changes." The letter `n` is *the size of your input* - the
number of items, rows, users, whatever you're working over.

📝 **Terminology.** *Input size* is what `n` stands for: how much stuff your code has to chew through.
1,000 users? `n` is 1,000. The whole point of Big-O is to describe behavior *as `n` gets large*,
because that's when the differences become impossible to ignore.

## Why "exact speed" is the wrong thing to measure

You might wonder: why not just measure seconds? Because seconds depend on a hundred things that have
nothing to do with your code - the machine, the language, what else is running, whether the data was
warm in cache. Run the same code on a laptop and a server and you'll get different numbers.

Big-O throws all of that away on purpose. It ignores the machine and asks only about the *shape* of
the growth. That's why a single Big-O label is true everywhere: an `O(n²)` algorithm has the squaring
problem on your laptop, on a supercomputer, and on a phone. The hardware changes how long each unit of
work takes; it does not change how the work *grows*.

💡 **Key point.** Big-O describes the *shape of the curve*, not a point on it. A faster computer slides
you along the same curve. It does not give you a different curve.

## Seeing the shapes

The reason growth matters so much is that the shapes pull apart violently as `n` gets big. At tiny
sizes they all look about the same. Then they don't.

Here's the same handful of inputs run through the common growth shapes. The numbers are the *amount of
work*, not seconds - counts of basic steps:

```text
   input size (n) →        10        100         1,000        1,000,000
   ─────────────────────────────────────────────────────────────────────
   O(1)   constant          1          1             1                 1
   O(log n) logarithmic    ~3         ~7           ~10               ~20
   O(n)   linear           10        100         1,000         1,000,000
   O(n log n)              ~30       ~700       ~10,000      ~20,000,000
   O(n²)  quadratic       100     10,000     1,000,000   1,000,000,000,000
```

*What just happened:* Look across the bottom row. When `n` is 10, the quadratic algorithm does 100
steps - totally fine. When `n` hits a million, it does a *trillion* steps. Meanwhile the `O(log n)`
row barely moved: from ~3 steps to ~20 across the entire range. Same inputs, wildly different fates.
That gap is the entire reason anyone cares about Big-O.

The numbers in that table are one thing; the *shapes* are what stick. Drag `n` below and watch the curves pull apart. The two hugging the bottom (`O(1)` and `O(log n)`) barely rise, the straight diagonal (`O(n)`) is plain and fine, and the one that rockets upward (`O(n²)`) is the cliff that looks harmless on the left and ruins your afternoon on the right.

```playground-bigo
```

*What just happened:* same inputs, wildly different fates. Slide `n` toward the right and the `O(n²)` count explodes while the flat shapes barely move. Most of the time your whole job is just to not be on that top curve when `n` gets big.

⚠️ **The trap of small inputs.** Everything looks fast when `n` is 10. That's exactly why bad scaling
hides - your code sails through testing with a few rows and then falls over in production with a few
million. Big-O is the tool that lets you *see the cliff before you drive off it.*

## So what is Big-O, in one sentence?

**Big-O is a label for how the work grows as the input grows - barely, linearly, or explosively - so
you can predict whether code that's fine today will survive when the data gets big.**

No limits. No proofs. Just: *double the input, what happens to the work?* Hold onto that question.
Everything in the next phase is just five common answers to it.

## Recap

1. Big-O measures **how work grows with input size**, not how many seconds something takes.
2. The one question: **double the input - does the work barely change, double, or square?**
3. `n` is the **input size**; Big-O describes behavior **as `n` gets large**.
4. The shapes look identical for tiny `n` and **pull apart violently** as `n` grows - which is why
   slow scaling hides during testing.
5. A faster machine moves you **along the same curve**; it doesn't give you a better one.

Next, the small set of shapes you'll actually run into - and how to name each one straight from the
code.

Watch how a simple sort actually moves the data - each comparison and swap is one step of work that grows with *n*:

```playground-sorting
```
