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
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++;