Asymptotic Analysis
We measure an algorithm's running time as a function of its input size, then strip away machine-specific constants and lower-order terms to compare algorithms cleanly. This lesson defines the RAM model and the , , , , and notations, proves the polynomial theorem, and shows how to rank growth rates with the limit test, L'Hôpital, base substitution, and the logarithm identities the arguments lean on.
╌╌╌╌
In the previous lesson we saw the same algorithm, insertion sort, cost quadratically many comparisons on one input and linearly many on another, all on the same machine. To compare algorithms as algorithms, independent of the hardware and the particular input, we need two things: a model of computation abstract enough to ignore the machine, and a notation coarse enough to ignore constants. This lesson supplies both.
The RAM model of computation
We analyze algorithms against an idealized machine, the random-access machine (RAM). It has the properties CLRS, Skiena, and Erickson all assume, usually tacitly:
- Instructions execute one at a time, no concurrency.
- The basic operations, namely arithmetic (, , , ), comparisons, data movement (load, store, copy), and control flow, each take a constant amount of time.
- Memory is an unbounded array of cells, and accessing any cell by its index costs the same constant (this is what random access means).
- Each cell holds an integer or float of
reasonable
size, roughly bits for an input of size , so a single value fits in a machine word.
The RAM is a deliberate fiction. Real multiplication is not truly constant-time for arbitrarily large numbers; real memory has caches that make some accesses far cheaper than others. But the model is predictive: an algorithm that is fast on the RAM is, overwhelmingly, fast in practice. Skiena stresses this engineering payoff;1 CLRS is careful to flag the places, such as bignum arithmetic, where the constant-word assumption breaks down.2
From problem to
It helps to be precise about what we are even measuring. A
computational problem is just a function
from a set of possible inputs to a set of possible outputs; each element
is an instance of . Sorting integer arrays, for
example, has . A size function
records how big
each instance
is. For an array we take . An algorithm solves if for every
instance .
Now charge = the number of elementary RAM operations performs on input . Inputs of the same size can cost different amounts, so we take the worst one of each size:
When the algorithm is understood, this is the function we denote , the running time as a function of the input size . The size is usually the number of elements, but sometimes the number of bits, or two parameters (e.g. and for a graph); choosing the right size measure is the first decision in any analysis. What we ultimately want is a good, convenient-to-understand upper bound on , which is what the notation below provides.
Worst, average, and best case
For a fixed input size , different inputs of that size may cost different amounts. Insertion sort costs on a sorted array and on a reversed one. So is not one number; it is a range. We summarize it three ways:
- Worst case : the maximum cost over all inputs of size .
- Best case: the minimum cost over all inputs of size .
- Average case: the expected cost over a probability distribution on inputs of size (usually the uniform distribution).
We almost always report the worst case. It is a guarantee: the algorithm never does worse, no matter how adversarial the input. The best case is nearly useless as a promise, since any algorithm looks good on its luckiest input. The average case is the most honest predictor of typical performance but requires us to commit to a distribution, and the analysis is usually harder (it often needs the probabilistic tools of a later module). CLRS develops all three; Skiena argues that for design purposes the worst case is what you should plan for.
Why we drop constants and lower-order terms
Suppose careful counting gives the running time of some algorithm as
Two facts make most of this expression noise:
- The leading term dominates. As grows, swamps . At the quadratic term is and the rest is , under . The growth rate is governed entirely by .
- The constants are machine artifacts. The depends on how many RAM operations our particular pseudocode spends per iteration; recompile on a different machine and it changes. It says nothing about the algorithm's intrinsic scaling.
So we throw both away and say the running time is order . This is the
right level of abstraction. An algorithm with a tiny
constant still loses eventually to an algorithm with a large one,
and eventually
is what asymptotic analysis captures. The notation below
makes order
precise.
The asymptotic notations
Let and be functions from the positive integers to the nonnegative reals. The notations describe how behaves relative to for all sufficiently large .
Big-O: asymptotic upper bound
State it as a clean existential:
The constant lets us ignore multiplicative factors; the threshold lets us ignore small inputs where lower-order terms might still dominate. (CLRS phrases as a set of functions and adds to keep things nonnegative; the two readings agree.)
The picture to keep in mind is the for large
sketch: the scaled curve
rises above once passes the threshold , and stays above
forever after. What happens to the left of is irrelevant.
The wanted inequality
method. Proofs of -bounds follow a fixed recipe:
write down the inequality you want to hold, then reverse-engineer constants
and that make it true. To prove , we want
. For each lower term is at most , so
; thus ,
work. The same move handles any polynomial; see the theorem below.
Big-Omega: asymptotic lower bound
Mirror the quantifiers, flip the inequality:
It is the mirror image of : if and only if .
Big-Theta: asymptotic tight bound
pins between two constant multiples of : it grows exactly as fast as , up to constants. The fundamental link is
When we say insertion sort is in the worst case,
we mean its
worst-case cost is sandwiched between and , a precise,
two-sided claim. When we only have an upper bound we say ; this is why people
loosely write even where holds. But the distinction matters, as the
next two results show.
The polynomial theorem
The single most useful fact for everyday analysis collapses every polynomial to its leading power:
is an upper bound, not a promise of tightness
Consider a worked cautionary case. Exchange sort compares with for every pair , so its running time satisfies
by the polynomial theorem. But also implies the true but useless statement : a correct upper bound need not be tight. So how loose can we go? Not below . The number of pairs is itself a lower bound on the work:
This forces ; indeed for any . No constant can keep under once is large enough, because whenever . The moral: alone tells you the cost is no worse than something; only matching it with (i.e. proving ) certifies you have found the true growth rate.
Picture the exponents on a line. Exchange sort's cost sits at . Every with is a valid upper bound, but only is tight; the side forbids any upper bound with , walling off the left. Where the two bounds meet is .
Little-o and little-omega: strict bounds
and allow and to grow at the same rate. The lowercase versions forbid that; they assert a strict gap.
So means becomes negligible compared to (, ), and means dominates (, ) — mirror images, since . A useful analogy from CLRS: are to functions as are to numbers.
Strict implies loose, never the reverse
Little-o strengthens . If , then the inequality holds in particular for past some threshold, and with that threshold witnesses . So , and by the mirror argument . The containment is proper, and the counterexample is as small as they come:
The picture to hold: is the part of that keeps a widening gap below , and is the part that tracks exactly. The two cannot overlap: if then eventually drops below for every candidate lower constant , so no bound, and hence no bound, can hold. The sets , , and are pairwise disjoint, which is precisely what the strict/tight/strict labels in the figure record.
One warning before leaning on the number analogy too hard. Real numbers obey trichotomy: for any , exactly one of , , holds. Functions do not. CLRS's example is versus : the exponent oscillates between and forever, so the second function is neither nor , and the pair cannot be ranked at all.3 Asymptotic comparison is a partial order, not a total one. In practice the running times we meet are comparable, but proofs should never assume two functions can be ordered.
Comparing functions with limits
The limit of the ratio is how you rank growth rates:
One caution. The test is sufficient, not necessary: the limit may fail to exist even when a -bound holds. The function hops between and forever, so has no limit, yet with and . When the ratio oscillates, fall back on the quantifier definitions; they are the ground truth, and the limit forms are a convenience layered on top.4
The ratio test, worked three times
The method: form the ratio, simplify it until its limit is readable, and apply the case table above. Three comparisons cover the moves that recur in practice.
1. vs : L'Hôpital on the leftover. Divide out the shared factor of first:
Numerator and denominator both tend to infinity, and both are differentiable as functions of a real variable , so L'Hôpital's rule applies (switch to ; the base costs only a constant factor):
So : any polynomial exponent strictly above , however slightly, eventually outgrows . The crossover is remote, though. The ratio only drops below once , which first happens around , on the order of . For every input you will ever benchmark, looks bigger; the limit says the polynomial wins anyway.
2. Polylogs vs polynomials: substitute . Claim: for all constants ,
so every polynomial beats every polylogarithm.5 The ratio mixes a log and a power awkwardly; the fix is a change of variable. Set (so , and exactly when ):
This is now a polynomial in against an exponential in . Take of the ratio:
because (the , exponent- case of comparison 1). A quantity whose logarithm tends to tends to , so the ratio vanishes and the claim holds. Erickson's slogan for the general principle: take logs until the comparison becomes one you already know.
3. vs : take the log of the ratio. The same move settles polynomials against exponentials directly:
since by comparison 2. Hence , i.e. for every fixed ; even is eventually dominated by . Read backwards, : no polynomial upper bound of any degree can hold for an exponential.
Small inputs lie
Comparison 2 comes with the same caveat as comparison 1: the crossover can sit far beyond any table of test values. Take , , that is, against . The two are equal exactly when for , and gives on both sides. So the polylog stays above the polynomial for every up to , and near it is ahead by a factor of about . An empirical plot stopping at would rank the two backwards; the limit gets it right.
Why we write with no base. Inside asymptotic notation the base is irrelevant, because changing base only multiplies by a constant:
So , , and all live in the same -class, and means the same thing whichever base you had in mind. (The constant is the multiplicative factor and are designed to absorb.)
The logarithm identities analysis leans on
Base-changing is one of a small kit of identities that carry most asymptotic arguments involving logs:6
Each has a specific role. The product rule turns products into sums, which is how one analyzes anything defined multiplicatively; the log of becomes the sum , handled below. The power rule pulls exponents out front, so : the logarithm of any polynomial in is just , degree notwithstanding. And base-change is the license to write bare .
One less familiar identity swaps a base against an exponent:
Its use is cosmetic but constant: it rewrites an exponential in as a plain polynomial. For instance , a shape that will fall out of divide-and-conquer recurrences and would otherwise be hard to place in the hierarchy.
Finally, the sum promised above:
Stirling's approximation sharpens the same statement to ,7 but the half-the-terms trick above is the version worth internalizing; it reappears whenever a sum needs a quick lower bound. This bound is also why comparison sorts that do work are optimal in a sense we will prove later.
With the notations defined and the ranking machinery in hand, the next lesson puts them to work: it lays out the standard growth hierarchy, proves the orderings between its rungs, and shows how to read the running time of a loop nest straight off the page. This continues in Growth Rates and Loop Analysis.
Takeaways
- The RAM model charges constant time per primitive operation and lets us measure running time as a function of input size, machine-independently.
- Report the worst case by default: it is a guarantee. Best case promises nothing; average case is honest but needs a distribution.
- Drop constants and lower-order terms. They are machine artifacts and noise; the leading term's growth rate is what scales.
- is an upper bound, a lower bound, a tight (two-sided) bound; and are their strict versions. and .
- alone certifies only that the cost is no worse than something; matching it with (proving ) is what pins the true growth rate. Comparison is a partial order — some function pairs, like and , cannot be ranked at all.
- The limit ranks two functions: , a constant, or give , , or . When the ratio is hard to evaluate, take its logarithm or substitute until the comparison becomes one you know.
- Small inputs lie. exceeds for every up to , and looks larger than out past ; only the limit verdict is final.
- Logarithms: the base never matters inside ; turns products into sums; turns exponentials in into plain polynomials; and by the half-the-terms trick.
Footnotes
- Skiena, §2 — Algorithm Analysis: the RAM model as a machine-independent abstraction whose engineering payoff is predicting real-world speed. ↩
- CLRS, Ch. 3 — Characterizing Running Times: the RAM model's constant-word assumption and where it breaks down (e.g. bignum arithmetic). ↩
- CLRS, Ch. 3 — Characterizing Running Times: asymptotic comparability is not total; and cannot be ranked. ↩
- CLRS, Ch. 3 — Characterizing Running Times: the limit characterizations of and ; the quantifier definitions remain the ground truth when the limit does not exist. ↩
- Erickson, Algorithms, Appendix — Solving Recurrences (analysis throughout): ranking growth rates by the limit of the ratio, so every polynomial dominates every polylogarithm. ↩
- Skiena, §2 — Algorithm Analysis: logarithm identities and their consequences for analysis, including why the base is irrelevant inside asymptotic notation. ↩
- CLRS, Ch. 3 — Characterizing Running Times: via Stirling's approximation. ↩
╌╌ END ╌╌