Skip to content
AI360XpertBeta

Big-O and Algorithm Complexity

Big-O describes how cost grows when the input grows, ignoring the constants. It tells you which algorithm wins at scale, before anyone runs anything.

Doubling n from 8 to 16 doubles a linear cost from 8 to 16 but quadruples a quadratic cost from 64 to 256, while a constant cost stays at 5
Doubling n from 8 to 16 doubles a linear cost from 8 to 16 but quadruples a quadratic cost from 64 to 256, while a constant cost stays at 5

Why Does This Exist?

Two correct programs can differ in cost by a factor of a million on real inputs, and the difference is visible before either one runs. A linear scan over a billion rows does a billion steps, while a quadratic comparison of the same rows does a billion billion. No machine, no optimiser, and no GPU closes that gap. Complexity analysis is how you see it coming.

The tool is asymptotic notation. Big-O gives an upper bound that grows no faster than, Omega gives a lower bound that grows no slower than, and Theta gives a tight bound that does both at once. When someone says attention is quadratic in sequence length, that is a Big-O claim with hardware consequences at billion-token scale.

This page teaches the definitions and the counting. What those counts mean on real accelerators, where moving bytes often costs more than arithmetic, is the sequel in computational complexity for ML.

The one idea you need first

Cost means operation count as a function of input size nn, written T(n)T(n). We study its shape as nn grows large, deliberately ignoring constant factors and small-nn behaviour. The payoff is comparison: shapes separate while constants merely shift. If summation notation is rusty, the refresher is summation and product notation.

Think of It Like This

Handshake rounds at parties

At a party, everyone shaking everyone else's hand takes about n2/2n^2 / 2 handshakes for nn guests. Ten guests means 45 handshakes, which is fine. A hundred guests means 4,950, and the evening is over.

Now change the ritual so everyone shakes only the host's hand. That is nn handshakes. A hundred guests means a hundred handshakes, and doubling the guest list merely doubles the work.

The first ritual is quadratic and the second is linear, and no faster hand-shaking closes the gap as parties grow. Big-O is the vocabulary that says so in one symbol: O(n2)O(n^2) versus O(n)O(n).

How It Actually Works

The three bounds, stated plainly, where f(n)f(n) is the true cost, g(n)g(n) is the reference shape, nn is input size, and CC and cc are positive constants:

  • f(n)=O(g(n))f(n) = O(g(n)) if f(n)≤C⋅g(n)f(n) \le C \cdot g(n) for all large nn. Upper bound: no faster growth than gg.
  • f(n)=Ω(g(n))f(n) = \Omega(g(n)) if f(n)≥c⋅g(n)f(n) \ge c \cdot g(n) for all large nn. Lower bound: no slower growth than gg.
  • f(n)=Θ(g(n))f(n) = \Theta(g(n)) if both hold. Tight bound: same growth shape as gg.

In practice the fastest-growing term decides everything. In 3n2+5n+73n^2 + 5n + 7, the n2n^2 term dominates past small nn, the constants 33, 55, and 77 wash out, and the whole thing is Θ(n2)\Theta(n^2). Formally, 3n2+5n+7≤4n23n^2 + 5n + 7 \le 4n^2 for all n≥6n \ge 6 with C=4C = 4, and it is ≥3n2\ge 3n^2 always with c=3c = 3.

Worked example

Double the input from n=8n = 8 to n=16n = 16 and watch each class respond:

  • constant O(1)O(1): 55 operations stay 55. Ratio 11.
  • linear O(n)O(n): 88 becomes 1616. Ratio 22.
  • quadratic O(n2)O(n^2): 6464 becomes 256256. Ratio 44.
  • cubic O(n3)O(n^3): 512512 becomes 4,0964{,}096. Ratio 88.

That ratio column is the whole game. A dense matrix multiply at n=4,096n = 4{,}096 does about 6.9×10106.9 \times 10^{10} multiply-adds, since 40963=68,719,476,7364096^3 = 68{,}719{,}476{,}736, which is why sequence length dominates transformer cost and why linear-time alternatives are such a prize. The diagram shows the first three rows: 55 staying 55, 88 doubling to 1616, and 6464 quadrupling to 256256.

Code

The point is the check: confirm the doubling ratios empirically with raw operation counts, no timers involved.

def op_count(n: int, kind: str) -> int:    if kind == "linear":        return n    if kind == "quadratic":        return n * n    raise ValueError("unknown kind")

for kind in ("linear", "quadratic"):    print(kind, op_count(16, kind) / op_count(8, kind))  # -> linear 2.0, quadratic 4.0

The printed ratios 2.02.0 and 4.04.0 match the theory exactly: doubling nn doubles linear work and quadruples quadratic work. Constants would cancel in the division even if the code counted them.

Watch Out For

Quoting Big-O while the constants decide the race

An O(n)O(n) method with a constant of 10,00010{,}000 loses to an O(n2)O(n^2) method with a constant of 11 for every nn below 10,00010{,}000. Asymptotics describe large nn, and your nn may not be large.

Symptom is a theoretically faster method losing in production on current sizes. Always ask what nn you actually run before letting the notation pick the algorithm.

Confusing worst case with the case you have

Quicksort is O(n2)O(n^2) worst case and O(nlog⁡n)O(n \log n) average case, and hash tables are O(1)O(1) until an adversary picks the keys. State which case a bound describes and check your inputs land in it.

Interview answers that skip this qualifier are where the follow-up question bites. Name the case: worst, average, and amortised bounds answer different questions.

The Quick Version

  • Big-O bounds growth from above, Omega from below, and Theta from both sides at once.
  • Only the fastest-growing term matters: 3n2+5n+73n^2 + 5n + 7 is Theta of n2n^2.
  • Doubling nn from 88 to 1616 moves linear 88 to 1616 and quadratic 6464 to 256256.
  • Constants and small-nn behaviour survive outside the notation, so check your actual nn.
  • Name the case: worst, average, and amortised bounds answer different questions.