Best, Worst and Average Case

The same algorithm can be lightning-fast on one input and crawl on another. Insertion sort skims through an already-sorted array but grinds through a reversed one; linear search may hit its target on the first probe or the last. So "how long does it take?" has no single answer for a given size n — it has a range, one number per possible input. To report a single running time we choose a lens onto that range: the best, worst, or average case.

These three are not competing definitions of speed — they answer three different questions. This page is about choosing the right lens, and about the single most common confusion in all of complexity: the lens (which input) is a completely separate axis from the asymptotic bound (which direction) you attach to it.

The three lenses

Fix an input size n and let T(x) be the running time on a specific input x of that size. The three lenses are three ways to summarise T over all inputs of size n:

The three lenses form an ordering for every n:

T_{\text{best}}(n) \;\le\; T_{\text{avg}}(n) \;\le\; T_{\text{worst}}(n).

For linear search over n elements these three curves fan out cleanly — a constant floor, a line through the middle, and a line at the top:

Why worst case is the default guarantee

Unless stated otherwise, "the running time of algorithm A" means its worst case. There are three good reasons the field settled on this lens:

Best case, by contrast, is almost always misleading: every algorithm has a lucky input, so "runs in \Theta(n) in the best case" tells you nothing about the input you actually hold. Quoting a rosy best case to sell an algorithm is a classic sleight of hand — bogosort's best case is \Theta(n) (the array happens to arrive sorted), yet no one would call it a good sort.

Average case: expectation over a distribution

The average case is the most informative and the most treacherous lens, because its answer depends entirely on the distribution \mathcal{D} you assume. "Average" is not a property of the algorithm alone — it is a property of the algorithm plus a model of its inputs. State the distribution or the number is meaningless.

The showcase is sorting-style analysis on quicksort. With a fixed pivot rule, an adversary can force \Theta(n^2) (feed it sorted data). But over a uniformly random permutation of the inputs, the expected number of comparisons is T_{\text{avg}}(n) = \Theta(n \log n), and the analysis runs straight through the harmonic sum H_n = \Theta(\log n) — element i and element j are compared with probability 2/(j-i+1), and summing those probabilities gives the n \log n. That single result — a worst-case-n^2 algorithm that is n \log n on average and blazingly fast in practice — is why the full average-case analysis earns a page of its own later in the course.

Because the worst case can be pessimistic to the point of dishonesty. Quicksort and the simplex method for linear programming both have exponential-or-quadratic worst cases that essentially never occur on real data — insisting on the worst case would have you reject two of the most successful algorithms ever written. Hash tables are \Theta(n) per lookup in the worst case (every key collides) yet \Theta(1) on average, which is the only reason we use them everywhere. Average case is how we explain the gap between a scary worst case and superb real-world performance — and randomised algorithms go one better, shuffling their own input so the good "average" holds no matter what the adversary sends.

The deepest confusion in this whole subject: best/worst/average (which input you measure) is a completely separate axis from $O$/$\Omega$/$\Theta$ (which direction you bound). You can attach any bound to any case. It is perfectly sensible to say insertion sort's worst case is \Theta(n^2) and \Omega(n^2) and O(n^2) — three bounds on one case. It is equally sensible to bound its best case as \Theta(n). The sentence "the algorithm is O(n^2)" does not mean "worst case", and "\Omega" does not mean "best case" — a lower bound can be on the worst case too (insertion sort is \Omega(n^2) in the worst case). Say both coordinates: "worst-case \Theta(n^2)", "best-case \Theta(n)". Anyone who conflates the two axes will eventually prove something false.

Worked example — linear search

Search an unsorted array of n elements for a target, scanning left to right.

function linearSearch(a: number[], target: number): number { for (let i = 0; i < a.length; i++) { if (a[i] === target) return i; // stop as soon as we find it } return -1; // not present }

So best case is \Theta(1) but both worst and average are \Theta(n) — halving the constant (n vs (n+1)/2) doesn't change the class. This is typical: the average often shares the worst case's growth rate, differing only in the constant, which is why the worst-case guarantee is usually a fair summary anyway.