Skip to content

Complexity and Big-O Notation: Measuring Speed as a Function of Input Size

Raw
  • Complexity is the number of basic operations executed on an input of size nn; it is not the running time measured in seconds. This abstraction is what makes comparisons independent of machine, language and compiler.
  • The statement f(n)=O(g(n))f(n) = O(g(n)) asserts that there exist constants c>0c > 0 and n0n_0 such that f(n)cg(n)f(n) \le c\,g(n) for every nn0n \ge n_0. Here O(g)O(g) is a set of functions, and the equality sign is nothing but a customary abbreviation.
  • Growth rates form a hierarchy 1lognnεnnlognn22nn!1 \prec \log n \prec n^{\varepsilon} \prec n \prec n\log n \prec n^2 \prec 2^n \prec n!. This is not an intuition but a theorem, provable as a statement about limits.
  • Doubling the input size multiplies the cost of a Θ(n2)\Theta(n^2) algorithm by 44, whereas a Θ(2n)\Theta(2^n) algorithm gains “all the work it had done so far” again. Making the machine 10001000 times faster raises the largest tractable nn for a Θ(2n)\Theta(2^n) algorithm by only about 1010.
  • For divide-and-conquer recurrences T(n)=aT(n/b)+f(n)T(n) = a\,T(n/b) + f(n), the master theorem determines the order mechanically.
  • The boundary between “solvable in polynomial time” and “only exponential algorithms known” lies at the heart of the P vs NP problem, the central open question of computer science.

1. Motivation: why growth rate rather than seconds

Section titled “1. Motivation: why growth rate rather than seconds”

Suppose we want to know which of two programs, A and B, is faster. The naive method is to run them and compare the elapsed seconds. This method has a decisive weakness: what we measured is the speed on that input, on that machine, with that compiler, in that cache state, and nothing guarantees the same ranking tomorrow in a different environment.

Worse, a measurement on small inputs predicts nothing about the behaviour on large ones. Consider two algorithms that sort an array of nn elements. Insertion sort performs about n2/2n^2/2 comparisons in the worst case, while merge sort performs about nlog2nn\log_2 n. For n=10n = 10 the counts are 4545 and 3333, barely distinguishable. For n=106n = 10^6 they become 5×10115 \times 10^{11} and 2×1072 \times 10^7, a ratio of about 2500025000. On a machine performing 10910^9 basic operations per second, the second finishes in 0.020.02 seconds while the first takes over eight minutes.

What matters here is not the quality of the implementation but the structure of how the operation count grows as nn increases. Better hardware and optimised code buy us, in most cases, a speedup by a constant factor. The choice of algorithm, by contrast, turns n2n^2 into nlognn\log n — a difference no constant factor can close.

We therefore regard the operation count as a function of nn and look only at the growth rate, discarding constant factors and finitely many exceptions. It is exactly this coarseness that makes universal, environment-independent comparison possible. Below we first decide what to count (§2), then make the comparison of growth rates precise (§3), prove the resulting hierarchy (§4), and see what happens at realistic scales (§5).

2. Preliminaries: the machine model and complexity

Section titled “2. Preliminaries: the machine model and complexity”

Before counting “basic operations” we must decide what a basic operation is. The standard choice is the uniform-cost RAM model (uniform-cost random access machine).

Definition 2.1The uniform-cost RAM model

The machine has a sequence of memory cells indexed by addresses 0,1,2,0, 1, 2, \ldots together with finitely many registers. Each of the following operations is called a basic operation and is executed in one unit of time.

  1. Reading from and writing to a constant, a register, or a memory cell at a specified address
  2. Addition, subtraction, multiplication, division and comparison of integers and reals
  3. Conditional and unconditional branching

Moreover, a single memory cell is assumed to hold a word of O(logn)O(\log n) bits, where nn is the input size.

The last condition is easy to overlook but essential. Without the restriction to O(logn)O(\log n) bits per word, one could pack the whole input into a single cell and perform multiple-precision arithmetic in one step, which would license wildly unrealistic algorithms. Under the restriction, on the other hand, the log2n\log_2 n bits needed to index nn elements fit into exactly one word, so array index computations take one step — a setting close to a real machine.

Remark 2.2

In the uniform-cost model, multiplying two kk-digit integers also counts as one step. In cryptography or computer algebra, where huge integers occur, this assumption fails and one uses the logarithmic-cost model, which charges a cost proportional to the number of bits. A complexity claim is meaningless unless the model it is measured in is stated.

Definition 2.3Worst-case time and space complexity

For an algorithm AA and an input xx, write tA(x)t_A(x) for the number of basic operations AA executes before halting on xx, and sA(x)s_A(x) for the total number of memory cells written to or read from. Define the size x|x| of an input xx to be the number of words needed to represent xx. Then

TA(n)=maxx=ntA(x),SA(n)=maxx=nsA(x)T_A(n) = \max_{|x| = n} t_A(x), \qquad S_A(n) = \max_{|x| = n} s_A(x)

are called the worst-case time complexity and the worst-case space complexity of AA.

Note the maximum. Time complexity refers to the least favourable input of size nn. Consequently TA(n)T_A(n) is an upper bound guaranteed for every input, once nn is fixed.

Time and space are not independent. The next proposition says that space is a “cheaper” resource than time.

Proposition 2.4Space is bounded by time

Suppose an algorithm AA accesses at most κ\kappa memory cells per basic operation (in the model of Definition 2.1 one may always take κ3\kappa \le 3). Then for every nn,

SA(n)n+κTA(n).S_A(n) \le n + \kappa\, T_A(n) .

In particular, if TA(n)nT_A(n) \ge n then SA(n)=O(TA(n))S_A(n) = O(T_A(n)).

Proof(Proposition 2.4)

Fix an input xx of size nn. Every cell accessed by AA is either one of the nn cells holding the input or a cell accessed during execution. By hypothesis at most κ\kappa cells are accessed per step, so at most κtA(x)\kappa\,t_A(x) cells are accessed over all tA(x)t_A(x) steps. Hence sA(x)n+κtA(x)n+κTA(n)s_A(x) \le n + \kappa\, t_A(x) \le n + \kappa\,T_A(n), and taking the maximum over x=n|x| = n gives the first claim.

If TA(n)nT_A(n) \ge n then n+κTA(n)(1+κ)TA(n)n + \kappa T_A(n) \le (1+\kappa) T_A(n), so taking c=1+κc = 1 + \kappa and n0=1n_0 = 1 in Definition 3.1 yields SA(n)=O(TA(n))S_A(n) = O(T_A(n)).

The converse fails. One can build algorithms using O(1)O(1) space and Θ(2n)\Theta(2^n) time at will. The asymmetry “memory can be reused, time cannot” shows itself here.

Example 2.5Counting the comparisons of insertion sort to the end

Consider insertion sort, which rearranges an array of length nn into increasing order.

def insertion_sort(a):
for i in range(1, len(a)):
key = a[i]
j = i - 1
while j >= 0 and a[j] > key:
a[j + 1] = a[j]
j -= 1
a[j + 1] = key
return a

Let us count how many times the comparison a[j] > key between elements is evaluated. Fix the outer loop variable ii; the inner while runs with j=i1,i2,j = i-1, i-2, \ldots decreasing. Because of short-circuit evaluation no comparison is performed once j >= 0 becomes false, so the number of comparisons equals the number of rounds with j0j \ge 0, that is, at most ii. This bound is attained exactly when the input is the strictly decreasing sequence a=(n,n1,,1)a = (n, n-1, \ldots, 1). Indeed, then key is always smaller than every element of a[0..i1]a[0..i-1], so the while runs until j=1j = -1, giving ii comparisons at j=i1,,0j = i-1, \ldots, 0. Hence the worst-case number of comparisons is

i=1n1i=n(n1)2.\sum_{i=1}^{n-1} i = \frac{n(n-1)}{2} .

For the same input the number of assignments is i=1n1(i+2)=n(n1)2+2(n1)\sum_{i=1}^{n-1}(i+2) = \frac{n(n-1)}{2} + 2(n-1), since for each ii the statement a[j+1]=a[j]a[j+1] = a[j] runs ii times and reading and writing key accounts for 22 more. Including loop control changes the total number of basic operations only by a constant factor, so T(n)=Θ(n2)T(n) = \Theta(n^2) (the meaning of Θ\Theta is given in Definition 3.1).

The storage used, beyond the input array, consists of the three words i, j, key, so the additional space is Θ(1)\Theta(1).

Remark 2.6

Besides worst-case complexity one can define average-case complexity, obtained by fixing a probability distribution on inputs and taking the expectation, and best-case complexity, attained on the most favourable input. The best case of insertion sort(Example 2.5) occurs on an already sorted input, with n1n-1 comparisons, that is Θ(n)\Theta(n). Quicksort is Θ(n2)\Theta(n^2) in the worst case yet Θ(nlogn)\Theta(n\log n) on average over random permutations (Theorem 5.5[Sorting Algorithms]), and in practice it is this average that governs. See Sorting algorithms for details. Unless stated otherwise, every complexity in this article is worst-case.

From now on f,gf, g denote nonnegative real-valued functions defined on N={1,2,}\mathbb{N} = \{1, 2, \ldots\}.

Definition 3.1The notations O, Ω and Θ

For a function gg, define the sets of functions O(g)O(g), Ω(g)\Omega(g), Θ(g)\Theta(g) by

O(g)={f  :  c>0, n0N, nn0, f(n)cg(n)}Ω(g)={f  :  c>0, n0N, nn0, f(n)cg(n)}Θ(g)=O(g)Ω(g)\begin{aligned} O(g) &= \{\, f \;:\; \exists c > 0,\ \exists n_0 \in \mathbb{N},\ \forall n \ge n_0,\ f(n) \le c\,g(n) \,\} \\ \Omega(g) &= \{\, f \;:\; \exists c > 0,\ \exists n_0 \in \mathbb{N},\ \forall n \ge n_0,\ f(n) \ge c\,g(n) \,\} \\ \Theta(g) &= O(g) \cap \Omega(g) \end{aligned}

Customarily one writes f(n)=O(g(n))f(n) = O(g(n)) for fO(g)f \in O(g), read ”ff is of order at most gg”.

The order of the quantifiers is the crux. The constants cc and n0n_0 are chosen before nn; choosing a convenient cc separately for each nn is not permitted. If this order is broken, then fO(g)f \in O(g) holds for arbitrary ff and gg (with g>0g > 0), and the notation becomes vacuous.

flowchart LR
A["choose constants c and n0 first"] --> B["then for every n"] --> C["if n is at least n0 then f(n) is at most c·g(n)"]
What the definition of O notation asserts

The notations oo and ω\omega strengthen one quantifier.

Definition 3.2The notations o and ω

o(g)={f  :  c>0, n0N, nn0, f(n)cg(n)}ω(g)={f  :  c>0, n0N, nn0, f(n)cg(n)}\begin{aligned} o(g) &= \{\, f \;:\; \forall c > 0,\ \exists n_0 \in \mathbb{N},\ \forall n \ge n_0,\ f(n) \le c\,g(n) \,\} \\ \omega(g) &= \{\, f \;:\; \forall c > 0,\ \exists n_0 \in \mathbb{N},\ \forall n \ge n_0,\ f(n) \ge c\,g(n) \,\} \end{aligned}

When fo(g)f \in o(g) we say that ff is of strictly smaller order than gg.

Where OO said “for some cc”, oo says “for every cc”. That cc may be taken arbitrarily small means that f/gf/g tends to 00. The next proposition makes this precise.

Proposition 3.3The limit test

Assume g(n)>0g(n) > 0 for all sufficiently large nn and that the limit L=limnf(n)/g(n)L = \lim_{n \to \infty} f(n)/g(n) exists (possibly ++\infty). Then:

  1. If 0L<0 \le L < \infty then fO(g)f \in O(g).
  2. If 0<L<0 < L < \infty then fΘ(g)f \in \Theta(g).
  3. If L=0L = 0 then fo(g)f \in o(g).
  4. If L=L = \infty then fω(g)f \in \omega(g) and go(f)g \in o(f).
Proof(Proposition 3.3)
  1. Since L<L < \infty, taking ε=1\varepsilon = 1 in the definition of convergence gives an n1n_1 such that f(n)/g(n)<L+1f(n)/g(n) < L + 1 for nn1n \ge n_1. Multiplying by g(n)>0g(n) > 0 yields f(n)(L+1)g(n)f(n) \le (L+1)\,g(n). Taking c=L+1>0c = L+1 > 0 and n0=n1n_0 = n_1 in Definition 3.1 gives fO(g)f \in O(g).

  2. Assume in addition L>0L > 0. Taking ε=L/2>0\varepsilon = L/2 > 0 gives an n2n_2 such that f(n)/g(n)>LL/2=L/2f(n)/g(n) > L - L/2 = L/2 for nn2n \ge n_2, that is, f(n)(L/2)g(n)f(n) \ge (L/2)\,g(n). With c=L/2c = L/2 and n0=n2n_0 = n_2 we get fΩ(g)f \in \Omega(g), which together with part 1 gives fΘ(g)f \in \Theta(g).

  3. Assume L=0L = 0. Given any c>0c > 0, take ε=c\varepsilon = c in the definition of convergence: there is an n0n_0 with f(n)/g(n)<cf(n)/g(n) < c, that is f(n)cg(n)f(n) \le c\,g(n), for nn0n \ge n_0. As cc was arbitrary, Definition 3.2 gives fo(g)f \in o(g).

  4. Assume L=L = \infty. For any c>0c > 0, the definition of divergence supplies an n0n_0 with f(n)/g(n)>cf(n)/g(n) > c, that is f(n)cg(n)f(n) \ge c\,g(n), for nn0n \ge n_0. Hence fω(g)f \in \omega(g). Rereading the same inequality as g(n)(1/c)f(n)g(n) \le (1/c) f(n) and noting that c=1/cc' = 1/c ranges over all positive reals as cc does, we obtain go(f)g \in o(f).

When the limit fails to exist the test is unusable. The OO notation itself remains meaningful nonetheless (see Exercise 8.4).

Proposition 3.4Rules of calculation for O notation

Let f,f1,f2,g,g1,g2,hf, f_1, f_2, g, g_1, g_2, h be nonnegative real-valued functions. The following hold.

  1. (Reflexivity) fO(f)f \in O(f).
  2. (Transitivity) If fO(g)f \in O(g) and gO(h)g \in O(h) then fO(h)f \in O(h).
  3. (Scalar multiples) If λ>0\lambda > 0 and fO(g)f \in O(g) then λfO(g)\lambda f \in O(g).
  4. (Sums) If f1O(g1)f_1 \in O(g_1) and f2O(g2)f_2 \in O(g_2) then f1+f2O(max(g1,g2))f_1 + f_2 \in O(\max(g_1, g_2)), where max(g1,g2)\max(g_1,g_2) denotes the pointwise maximum.
  5. (Products) If f1O(g1)f_1 \in O(g_1) and f2O(g2)f_2 \in O(g_2) then f1f2O(g1g2)f_1 f_2 \in O(g_1 g_2).
Proof(Proposition 3.4)
  1. With c=1c = 1 and n0=1n_0 = 1 we have f(n)1f(n)f(n) \le 1 \cdot f(n) for every n1n \ge 1.

  2. By hypothesis there are c1>0,n1c_1 > 0, n_1 with f(n)c1g(n)f(n) \le c_1 g(n) for nn1n \ge n_1, and c2>0,n2c_2 > 0, n_2 with g(n)c2h(n)g(n) \le c_2 h(n) for nn2n \ge n_2. For nmax(n1,n2)n \ge \max(n_1, n_2), substituting the second inequality into the first gives f(n)c1g(n)c1c2h(n)f(n) \le c_1 g(n) \le c_1 c_2 h(n) (the direction of the inequality is preserved because c1>0c_1 > 0). Take c=c1c2c = c_1 c_2 and n0=max(n1,n2)n_0 = \max(n_1,n_2).

  3. If f(n)cg(n)f(n) \le c\,g(n) for nn0n \ge n_0, multiplying by λ>0\lambda > 0 gives λf(n)λcg(n)\lambda f(n) \le \lambda c\,g(n). Replace the constant by λc\lambda c.

  4. For nmax(n1,n2)n \ge \max(n_1,n_2), using gimax(g1,g2)g_i \le \max(g_1,g_2),

f1(n)+f2(n)c1g1(n)+c2g2(n)(c1+c2)max(g1(n),g2(n)).f_1(n) + f_2(n) \le c_1 g_1(n) + c_2 g_2(n) \le (c_1 + c_2)\max(g_1(n), g_2(n)) .

Take the constant to be c1+c2c_1 + c_2.

  1. For nmax(n1,n2)n \ge \max(n_1,n_2), since f1,f2,g1,g20f_1, f_2, g_1, g_2 \ge 0 the two inequalities may be multiplied, giving f1(n)f2(n)c1c2g1(n)g2(n)f_1(n) f_2(n) \le c_1 c_2\, g_1(n) g_2(n).

Rule 4 is the tool used most often in practice. The everyday reasoning “an algorithm spending O(nlogn)O(n\log n) on preprocessing and O(n2)O(n^2) on the main body costs O(n2)O(n^2) overall” is nothing but an application of this rule.

Proposition 3.5The order of a polynomial

Let d0d \ge 0 be an integer, let a0,,ada_0, \ldots, a_d be real with ad>0a_d > 0, and suppose p(n)=i=0dainip(n) = \sum_{i=0}^{d} a_i n^i is nonnegative for all sufficiently large nn. Then pΘ(nd)p \in \Theta(n^d).

Proof(Proposition 3.5)

First the upper bound. Put A=i=0daiA = \sum_{i=0}^{d} |a_i|. For n1n \ge 1 we have nindn^i \le n^d for 0id0 \le i \le d, so

p(n)i=0daini(i=0dai)nd=And.p(n) \le \sum_{i=0}^{d} |a_i|\, n^i \le \Big(\sum_{i=0}^{d} |a_i|\Big) n^d = A\,n^d .

Hence pO(nd)p \in O(n^d) with c=Ac = A and n0=1n_0 = 1.

Now the lower bound. Put B=i=0d1aiB = \sum_{i=0}^{d-1} |a_i| (for d=0d = 0 we have B=0B = 0 and what follows is trivially true). For n1n \ge 1,

p(n)=nd(ad+i=0d1ainid),i=0d1ainidi=0d1ainidBn,p(n) = n^d\Big(a_d + \sum_{i=0}^{d-1} a_i n^{i-d}\Big), \qquad \Big|\sum_{i=0}^{d-1} a_i n^{i-d}\Big| \le \sum_{i=0}^{d-1} |a_i|\, n^{i-d} \le \frac{B}{n} ,

where the last inequality uses nidn1n^{i-d} \le n^{-1}, valid since id1i \le d-1. Taking n0=2B/ad+1n_0 = \lceil 2B/a_d \rceil + 1, we have B/nad/2B/n \le a_d/2 for nn0n \ge n_0, whence

p(n)nd(adad2)=ad2nd.p(n) \ge n^d\Big(a_d - \frac{a_d}{2}\Big) = \frac{a_d}{2}\, n^d .

With c=ad/2>0c = a_d/2 > 0 this gives pΩ(nd)p \in \Omega(n^d). Combining the two bounds, pΘ(nd)p \in \Theta(n^d).

Remark 3.6

The equality sign in f(n)=O(g(n))f(n) = O(g(n)) is not symmetric. The statement n=O(n2)n = O(n^2) is correct, but one never writes O(n2)=nO(n^2) = n. Read the sign as "\in" or "\subseteq", from left to right. An occurrence of O()O(\cdot) in the middle of a formula stands for “some function satisfying that condition”. For instance,

i=1ni=n22+O(n)\sum_{i=1}^{n} i = \frac{n^2}{2} + O(n)

means “the difference between the left-hand side and n2/2n^2/2 is a function belonging to O(n)O(n)”. This convention was codified by Knuth (reference [2]).

Remark 3.7

Inside OO notation the base of a logarithm need not be written. By the change-of-base formula logan=logbn/logba\log_a n = \log_b n / \log_b a, the functions logan\log_a n and logbn\log_b n differ only by a positive constant factor, so Θ(logan)=Θ(logbn)\Theta(\log_a n) = \Theta(\log_b n). However, as 2log2n=n2^{\log_2 n} = n versus 2log10n=n0.3012^{\log_{10} n} = n^{0.301\ldots} shows, once the logarithm sits in an exponent the difference of base is no longer a constant factor. The base may be dropped inside OO only when the logarithm appears as a multiplicative factor.

The intuitions ”logn\log n is far smaller than nn” and “an exponential is far larger than a polynomial” are made precise by the following theorem. We first prove the underlying lemma.

Lemma 4.1Exponentials beat polynomials

Let c>1c > 1 and k0k \ge 0 be real. Then, as a limit in the real variable xx,

limxxkcx=0.\lim_{x \to \infty} \frac{x^k}{c^{\,x}} = 0 .
Proof(Lemma 4.1)

We first treat the case in which xx runs through the natural numbers nn. Since c>1c > 1 we may write h=c1>0h = c - 1 > 0. Put m=k+1m = \lceil k \rceil + 1, so that m>km > k. By the binomial theorem, for nmn \ge m,

cn=(1+h)n(nm)hm=n(n1)(nm+1)m!hm(nm+1)mm!hmc^{\,n} = (1+h)^n \ge \binom{n}{m} h^m = \frac{n(n-1)\cdots(n-m+1)}{m!}\,h^m \ge \frac{(n-m+1)^m}{m!}\,h^m

(here we used that each factor n,n1,,nm+1n, n-1, \ldots, n-m+1 is at least the smallest one, nm+1n-m+1). If moreover n2mn \ge 2m, then nm+1>nmn/2n - m + 1 > n - m \ge n/2, so

nkcnm!  nkhm(n/2)m=m!2mhm  nkm.\frac{n^k}{c^{\,n}} \le \frac{m!\; n^k}{h^m (n/2)^m} = \frac{m!\,2^m}{h^m}\; n^{\,k-m} .

Since m>km > k the exponent kmk - m is negative and the right-hand side tends to 00 as nn \to \infty. As nk/cn0n^k/c^n \ge 0, the squeeze theorem gives limnnk/cn=0\lim_{n\to\infty} n^k/c^n = 0.

Now the real variable case. For x1x \ge 1 put n=x+1n = \lfloor x \rfloor + 1, so that xnx \le n and n1xn - 1 \le x. Since k0k \ge 0 and c>1c > 1,

xkcxnkcn1=cnkcn.\frac{x^k}{c^{\,x}} \le \frac{n^k}{c^{\,n-1}} = c\cdot\frac{n^k}{c^{\,n}} .

As xx \to \infty we have nn \to \infty, and by the previous paragraph the right-hand side tends to 00. Hence limxxk/cx=0\lim_{x\to\infty} x^k/c^x = 0.

Theorem 4.2The hierarchy of growth rates

Let a>0a > 0, ε>0\varepsilon > 0, k0k \ge 0 and c>1c > 1 be arbitrary reals. Then

(log2n)ao(nε),nko(cn),cno(n!).(\log_2 n)^a \in o(n^{\varepsilon}), \qquad n^k \in o(c^{\,n}), \qquad c^{\,n} \in o(n!) .

In particular, taking ε=1\varepsilon = 1, a=1a = 1 and c=2c = 2, the functions log2n\log_2 n, nn, 2n2^n, n!n! are of strictly increasing order in this sequence.

Proof(Theorem 4.2)

First claim. Put t=log2nt = \log_2 n, so that n=2tn = 2^t and tt \to \infty as nn \to \infty. Then

(log2n)anε=ta2εt=ta(2ε)t.\frac{(\log_2 n)^a}{n^{\varepsilon}} = \frac{t^a}{2^{\varepsilon t}} = \frac{t^a}{(2^{\varepsilon})^{t}} .

Since ε>0\varepsilon > 0 we have 2ε>12^{\varepsilon} > 1, so applying Lemma 4.1 with c=2εc = 2^{\varepsilon}, k=ak = a and x=tx = t shows that this ratio tends to 00. By part 3 of Proposition 3.3, (log2n)ao(nε)(\log_2 n)^a \in o(n^{\varepsilon}).

Second claim. Applying Lemma 4.1 directly with x=nx = n gives nk/cn0n^k/c^n \to 0, and again part 3 of Proposition 3.3 yields nko(cn)n^k \in o(c^n).

Third claim. Put m=2cm = \lceil 2c \rceil. For n>mn > m we may factor

cnn!=cmm!j=m+1ncj.\frac{c^{\,n}}{n!} = \frac{c^{\,m}}{m!}\prod_{j=m+1}^{n} \frac{c}{j} .

Since jm+1>2cj \ge m+1 > 2c, each factor satisfies c/j<1/2c/j < 1/2, so the product is at most (1/2)nm(1/2)^{\,n-m}. Hence

0cnn!cmm!(12)nm,0 \le \frac{c^{\,n}}{n!} \le \frac{c^{\,m}}{m!}\left(\frac{1}{2}\right)^{n-m} ,

and the right-hand side tends to 00 as nn \to \infty (here cc and mm are constants not depending on nn). By the squeeze theorem cn/n!0c^n/n! \to 0, that is, cno(n!)c^n \in o(n!).

The first claim says that however small ε>0\varepsilon > 0 is chosen, nεn^{\varepsilon} eventually exceeds (logn)100(\log n)^{100}: logarithms grow that slowly. The second says that 1.001n1.001^n eventually exceeds n1000n^{1000}: exponentials grow that fast. These two facts are the source of the dramatic differences seen in the next section.

1816243202550751002ⁿn log nnlog nn (input size)number of basic operations
Representative growth rates (the vertical axis is truncated at 100)

The handiest way to grasp the character of each class is to ask what happens to the running time when the input size is doubled.

Proposition 5.1The ratio under doubling of the input

Let α>0\alpha > 0 and β\beta be constants and k>0k > 0 real. The following hold.

  1. If T(n)=αT(n) = \alpha then T(2n)/T(n)=1T(2n)/T(n) = 1.
  2. If T(n)=αlog2n+βT(n) = \alpha \log_2 n + \beta then T(2n)T(n)=αT(2n) - T(n) = \alpha (the difference, not the ratio, is constant).
  3. If T(n)=αnkT(n) = \alpha n^{k} then T(2n)/T(n)=2kT(2n)/T(n) = 2^{k}.
  4. If T(n)=αnlog2nT(n) = \alpha n \log_2 n then T(2n)/T(n)=2(1+1log2n)T(2n)/T(n) = 2\left(1 + \dfrac{1}{\log_2 n}\right), which tends to 22 as nn \to \infty.
  5. If T(n)=α2nT(n) = \alpha\, 2^{n} then T(2n)/T(n)=2nT(2n)/T(n) = 2^{n}.
Proof(Proposition 5.1)

Each case is a direct substitution.

  1. T(2n)/T(n)=α/α=1T(2n)/T(n) = \alpha/\alpha = 1.
  2. T(2n)T(n)=α(log22nlog2n)+(ββ)=αlog22=αT(2n) - T(n) = \alpha(\log_2 2n - \log_2 n) + (\beta - \beta) = \alpha \log_2 2 = \alpha.
  3. T(2n)/T(n)=α(2n)k/(αnk)=2knk/nk=2kT(2n)/T(n) = \alpha (2n)^k / (\alpha n^k) = 2^k n^k / n^k = 2^k.
  4. T(2n)/T(n)=α2nlog22nαnlog2n=2log2n+1log2n=2(1+1log2n)T(2n)/T(n) = \dfrac{\alpha \cdot 2n \log_2 2n}{\alpha\, n \log_2 n} = 2\cdot\dfrac{\log_2 n + 1}{\log_2 n} = 2\left(1 + \dfrac{1}{\log_2 n}\right). As nn \to \infty we have 1/log2n01/\log_2 n \to 0, so the ratio tends to 22.
  5. T(2n)/T(n)=α22n/(α2n)=22nn=2nT(2n)/T(n) = \alpha 2^{2n}/(\alpha 2^{n}) = 2^{2n-n} = 2^{n}.

Claim 5 expresses the horror of exponential time in a single line. Having solved an instance with n=40n = 40, moving on to n=80n = 80 multiplies the time by 2401.1×10122^{40} \approx 1.1\times 10^{12}.

Remark 5.2

Proposition 5.1 is a statement about functions of exactly those forms; the hypothesis TΘ(n)T \in \Theta(n) alone does not imply T(2n)/T(n)2T(2n)/T(n) \to 2. For a counterexample take T(n)=n(2+sinn)T(n) = n\,(2 + \sin n). Since 12+sinn31 \le 2+\sin n \le 3 we have TΘ(n)T \in \Theta(n), yet T(2n)/T(n)=2(2+sin2n)/(2+sinn)T(2n)/T(n) = 2(2+\sin 2n)/(2+\sin n) oscillates between 2/32/3 and 66 and does not converge. Because Θ\Theta discards constant factors, it does not pin down the limit of the ratio.

Example 5.3Operation counts and running times in practice

Assume a machine performing 10910^9 basic operations per second. The operation counts are as follows.

nnlog2n\log_2 nnnnlog2nn\log_2 nn2n^22n2^n
10103.33.31010333310210^{2}1.0×1031.0\times10^{3}
1001006.66.610010066466410410^{4}1.3×10301.3\times10^{30}
10310^{3}10.010.010310^{3}1.0×1041.0\times10^{4}10610^{6}astronomical
10610^{6}19.919.910610^{6}2.0×1072.0\times10^{7}101210^{12}astronomical
10910^{9}29.929.910910^{9}3.0×10103.0\times10^{10}101810^{18}astronomical

Translated into time:

T(n)T(n)n=106n = 10^{6}n=109n = 10^{9}
nn0.0010.001 s11 s
nlog2nn\log_2 n0.020.02 s3030 s
n2n^21717 min3232 years

Look at the nlog2nn\log_2 n row. Even at n=109n = 10^9 the factor log2n\log_2 n is only 3030, so nlognn\log n is at most thirty times nn. Over the range of realistic input sizes, Θ(nlogn)\Theta(n\log n) is barely distinguishable from Θ(n)\Theta(n). This is why Θ(nlogn)\Theta(n\log n) algorithms such as comparison sorting and the fast Fourier transform are treated as “essentially linear”. The same applies to Θ(logn)\Theta(\log n): as nn grows a hundred-million-fold from 1010 to 10910^9, the value of log2n\log_2 n grows only ninefold, from 3.33.3 to 29.929.9. That is why binary search appears to finish instantly regardless of the number of elements (see Theorem 3.3[探索アルゴリズム] and Search algorithms).

Look at the exponential side as well. Performing 2501.1×10152^{50} \approx 1.1\times10^{15} operations takes about 1313 days, and 21001.3×10302^{100} \approx 1.3\times10^{30} operations about 4×10134\times10^{13} years, roughly 29002900 times the age of the universe (about 1.4×10101.4\times10^{10} years). Factorials grow even faster: 20!2.4×101820! \approx 2.4\times10^{18} corresponds to about 7777 years.

The essential difficulty of exponential time is clearest in the following comparison.

Example 5.4What if the machine becomes 1000 times faster

We compare the largest nn that can be handled within one second on a machine performing 10910^9 operations per second and on one performing 101210^{12}.

T(n)T(n)10910^{9} ops/s101210^{12} ops/schange
nn10910^{9}101210^{12}×1000\times 1000
nlog2nn\log_2 n4.0×1074.0\times10^{7}2.9×10102.9\times10^{10}about ×730\times 730
n2n^23.2×1043.2\times10^{4}10610^{6}about ×31.6\times 31.6
n3n^310310^{3}10410^{4}×10\times 10
2n2^n29293939+10+10

Let us verify the last row. Solving 2n=t2^{n} = t gives n=log2tn = \log_2 t, so multiplying tt by 10001000 increases nn by log21000=9.97\log_2 1000 = 9.97, that is, by about 1010. This is a general fact independent of the machine’s speed: for T(n)=αcnT(n) = \alpha\,c^{n} the increase is logc1000\log_c 1000.

In the n2n^2 row the improvement is a factor 1000=31.6\sqrt{1000} = 31.6, in the n3n^3 row a factor 10001/3=101000^{1/3} = 10 — that is, the reciprocal power of the exponent. In general, for T(n)=αnkT(n) = \alpha n^{k}, a machine ss times faster handles nn larger by a factor s1/ks^{1/k}.

The conclusion is unambiguous. For polynomial time, advances in hardware help; for exponential time, they hardly help at all. The only way through the exponential wall is a better algorithm.

Example 5.5From brute force to dynamic programming

Given nn positive integers w1,,wnw_1, \ldots, w_n and a target WW, decide whether some subset sums to exactly WW (the subset-sum problem). Brute force enumerates all subsets, examining 2n2^n of them, for a total of Θ(2nn)\Theta(2^n \cdot n). For n=40n = 40 this is 240×404.4×10132^{40} \times 40 \approx 4.4\times10^{13} operations, about 1212 hours on a machine doing 10910^9 operations per second.

By contrast, dynamic programming that fills a table b[i][w]b[i][w] recording whether the sum ww is attainable from the first ii items costs only Θ(nW)\Theta(nW). For n=40n = 40 and W=104W = 10^4 that is 4×1054\times10^5 operations, or 0.00040.0004 seconds — a speedup of more than thirty million, obtained not by changing the machine but simply by no longer recomputing the same partial sums over and over (recurrences of this shape and their complexity are treated in Corollary 6.4[動的計画法]; see Dynamic programming).

Note that Θ(nW)\Theta(nW) is not polynomial in the input size. Representing WW requires log2W\log_2 W bits, so WW can be exponentially large in the input size. Complexities of this kind are called pseudo-polynomial time.

The same operation can have different complexity depending on the data structure. Here are the worst-case complexities of the standard structures, with nn the number of stored elements.

operationunsorted arraysorted arraylinked listbalanced BSThash table
search for a valueΘ(n)\Theta(n)Θ(logn)\Theta(\log n)Θ(n)\Theta(n)Θ(logn)\Theta(\log n)avg. Θ(1)\Theta(1) / worst Θ(n)\Theta(n)
insertionΘ(1)\Theta(1) (at the end)Θ(n)\Theta(n)Θ(1)\Theta(1) (position known)Θ(logn)\Theta(\log n)avg. Θ(1)\Theta(1)
deletionΘ(n)\Theta(n) (search included)Θ(n)\Theta(n)Θ(1)\Theta(1) (position known)Θ(logn)\Theta(\log n)avg. Θ(1)\Theta(1)
retrieval of the minimumΘ(n)\Theta(n)Θ(1)\Theta(1)Θ(n)\Theta(n)Θ(logn)\Theta(\log n)Θ(n)\Theta(n)

There is no universally best structure. A sorted array searches quickly but requires shifting everything on insertion, while a linked list inserts quickly but needs Θ(k)\Theta(k) time to reach the kk-th element (Proposition 4.2[Fundamental Data Structures]). One decides what should be fast first, and chooses the structure afterwards. The definitions of these structures and the proofs of these complexities are treated in Fundamental data structures.

Remark 5.6

The entry ”Θ(1)\Theta(1) for appending to an unsorted array” assumes there is spare capacity. When the capacity is exhausted, a new region is allocated and all elements are copied, so that particular operation costs Θ(n)\Theta(n). If, however, the capacity is doubled each time it runs out, then starting from capacity 11 and performing nn insertions, copying occurs only when the number of elements is 1,2,4,,2k1, 2, 4, \ldots, 2^{k} with 2k<n2^{k} < n, and the total number of copies is

1+2+4++2k=2k+11<2n.1 + 2 + 4 + \cdots + 2^{k} = 2^{k+1} - 1 < 2n .

Since the total cost of nn insertions is O(n)O(n), the average per operation is O(1)O(1). Complexity averaged over a whole sequence of operations in this way is called amortised complexity (stated as a theorem, this estimate is Theorem 3.3[Fundamental Data Structures]). It is a different notion from the worst-case complexity of an individual operation, and the two should be kept apart.

6. Divide and conquer: from a recurrence to an order

Section titled “6. Divide and conquer: from a recurrence to an order”

The complexity of a recursive algorithm appears as a recurrence. For merge sort, an array of length nn is split in half, the halves are sorted recursively, and merging takes Θ(n)\Theta(n) time, giving T(n)=2T(n/2)+Θ(n)T(n) = 2\,T(n/2) + \Theta(n) (Theorem 4.2[Sorting Algorithms]). Recurrences of this shape are solved at a stroke by the following theorem.

Theorem 6.1The master theorem

Let a1a \ge 1 and b>1b > 1 be real, let d>0d > 0 be a constant, and let ff be a positive-valued function defined on the powers of bb. Suppose the function TT satisfies

T(1)=d,T(n)=aT(n/b)+f(n)(n=bk, k1).T(1) = d, \qquad T(n) = a\,T(n/b) + f(n) \quad (n = b^{k},\ k \ge 1) .

With nn ranging over the powers of bb, the following hold.

  1. If f(n)=O ⁣(nlogbaε)f(n) = O\!\left(n^{\log_b a - \varepsilon}\right) for some ε>0\varepsilon > 0, then T(n)=Θ ⁣(nlogba)T(n) = \Theta\!\left(n^{\log_b a}\right).
  2. If f(n)=Θ ⁣(nlogba)f(n) = \Theta\!\left(n^{\log_b a}\right), then T(n)=Θ ⁣(nlogbalogn)T(n) = \Theta\!\left(n^{\log_b a}\log n\right).
  3. If f(n)=Ω ⁣(nlogba+ε)f(n) = \Omega\!\left(n^{\log_b a + \varepsilon}\right) for some ε>0\varepsilon > 0 and, in addition, there is a constant 0<c<10 < c < 1 with af(bk1)cf(bk)a\,f(b^{k-1}) \le c\,f(b^{k}) for all k1k \ge 1 (the regularity condition), then T(n)=Θ(f(n))T(n) = \Theta(f(n)).
Proof(Theorem 6.1)

Let n=bkn = b^{k}. Unfolding the recurrence kk times gives

T(n)=akT(1)+j=0k1ajf ⁣(nbj)T(n) = a^{k} T(1) + \sum_{j=0}^{k-1} a^{j} f\!\left(\frac{n}{b^{j}}\right)

(by induction on kk: for k=0k=0 both sides equal T(1)T(1), and if the identity holds for kk, substituting it into T(bk+1)=aT(bk)+f(bk+1)T(b^{k+1}) = aT(b^{k}) + f(b^{k+1}) gives it for k+1k+1). Here

ak=alogbn=(blogba)logbn=(blogbn)logba=nlogba,a^{k} = a^{\log_b n} = \left(b^{\log_b a}\right)^{\log_b n} = \left(b^{\log_b n}\right)^{\log_b a} = n^{\log_b a} ,

so the first term is dnlogbad\,n^{\log_b a}. Since f>0f > 0, we always have T(n)dnlogbaT(n) \ge d\,n^{\log_b a}. It remains to estimate the sum Σ=j=0k1ajf(n/bj)\Sigma = \sum_{j=0}^{k-1} a^{j} f(n/b^{j}).

Case 1. By hypothesis there is a C>0C > 0 with f(m)Cmlogbaεf(m) \le C\,m^{\log_b a - \varepsilon} for all sufficiently large powers mm of bb. Then

ΣCj=0k1aj(nbj)logbaε=Cnlogbaεj=0k1ajbj(logbaε).\Sigma \le C \sum_{j=0}^{k-1} a^{j}\left(\frac{n}{b^{j}}\right)^{\log_b a - \varepsilon} = C\,n^{\log_b a - \varepsilon} \sum_{j=0}^{k-1} a^{j}\, b^{-j(\log_b a - \varepsilon)} .

Since bjlogba=ajb^{-j\log_b a} = a^{-j}, we have ajbj(logbaε)=(bε)ja^{j} b^{-j(\log_b a - \varepsilon)} = (b^{\varepsilon})^{j}, and the formula for a geometric series gives

j=0k1(bε)j=bεk1bε1<nεbε1\sum_{j=0}^{k-1} (b^{\varepsilon})^{j} = \frac{b^{\varepsilon k} - 1}{b^{\varepsilon} - 1} < \frac{n^{\varepsilon}}{b^{\varepsilon} - 1}

(using bεk=(bk)ε=nεb^{\varepsilon k} = (b^{k})^{\varepsilon} = n^{\varepsilon}). Hence Σ<Cbε1nlogba\Sigma < \dfrac{C}{b^{\varepsilon}-1}\,n^{\log_b a} and T(n)=O(nlogba)T(n) = O(n^{\log_b a}). The lower bound is the inequality T(n)dnlogbaT(n) \ge d\,n^{\log_b a} noted above, so together T(n)=Θ(nlogba)T(n) = \Theta(n^{\log_b a}).

Case 2. By hypothesis there are c1,c2>0c_1, c_2 > 0 with c1mlogbaf(m)c2mlogbac_1 m^{\log_b a} \le f(m) \le c_2 m^{\log_b a}. Since aj(n/bj)logba=ajnlogbaaj=nlogbaa^{j}(n/b^{j})^{\log_b a} = a^{j} n^{\log_b a} a^{-j} = n^{\log_b a}, every term of the sum lies between c1nlogbac_1 n^{\log_b a} and c2nlogbac_2 n^{\log_b a}. There are k=logbnk = \log_b n terms, so

c1nlogbalogbnΣc2nlogbalogbn.c_1\,n^{\log_b a} \log_b n \le \Sigma \le c_2\,n^{\log_b a}\log_b n .

As logbn\log_b n and logn\log n differ only by a positive constant factor (Remark 3.7), Σ=Θ(nlogbalogn)\Sigma = \Theta(n^{\log_b a}\log n). The first term dnlogbad\,n^{\log_b a} is absorbed into this, so T(n)=Θ(nlogbalogn)T(n) = \Theta(n^{\log_b a}\log n).

Case 3. From the regularity condition one proves ajf(n/bj)cjf(n)a^{j} f(n/b^{j}) \le c^{\,j} f(n) by induction on jj. Indeed, for j=0j = 0 this is an equality. Assuming it for jj and applying the regularity condition at n/bjn/b^{j}, we have af(n/bj+1)cf(n/bj)a f(n/b^{j+1}) \le c f(n/b^{j}), whence

aj+1f(n/bj+1)=ajaf(n/bj+1)ajcf(n/bj)ccjf(n)=cj+1f(n).a^{j+1} f(n/b^{j+1}) = a^{j}\cdot a f(n/b^{j+1}) \le a^{j}\, c\, f(n/b^{j}) \le c\cdot c^{\,j} f(n) = c^{\,j+1} f(n) .

Therefore, since 0<c<10 < c < 1,

Σf(n)j=0k1cj<f(n)1c.\Sigma \le f(n) \sum_{j=0}^{k-1} c^{\,j} < \frac{f(n)}{1-c} .

Moreover, the hypothesis f(n)=Ω(nlogba+ε)f(n) = \Omega(n^{\log_b a + \varepsilon}) gives a c3>0c_3 > 0 such that nlogbaf(n)c3nεf(n)c3n^{\log_b a} \le \dfrac{f(n)}{c_3\,n^{\varepsilon}} \le \dfrac{f(n)}{c_3} for all sufficiently large nn, so the first term is also O(f(n))O(f(n)). Hence T(n)=O(f(n))T(n) = O(f(n)). On the other hand, keeping only the j=0j = 0 term of the expansion gives T(n)f(n)T(n) \ge f(n), so T(n)=Ω(f(n))T(n) = \Omega(f(n)), and therefore T(n)=Θ(f(n))T(n) = \Theta(f(n)).

Remark 6.2

In real algorithms n/bn/b need not be an integer, and the recurrence takes the form T(n)=aT(n/b)+f(n)T(n) = a\,T(\lfloor n/b\rfloor) + f(n). It is known that the same conclusions as in Theorem 6.1 hold for this floor-function version; the proof is in Chapter 4 of Cormen et al. (reference [1]). That book also states the regularity condition in the weaker form “for all sufficiently large nn”. Even in this weaker form the conclusion is unchanged, since at most logbn0+1\log_b n_0 + 1 terms violate the condition and each of them is O(nlogba)=O(f(n))O(n^{\log_b a}) = O(f(n)). Techniques for recurrences to which the master theorem does not apply are treated in the Appendix.

Example 6.3Applying the master theorem

(a) Merge sort. For T(n)=2T(n/2)+Θ(n)T(n) = 2\,T(n/2) + \Theta(n) we have a=2a = 2, b=2b = 2, f(n)=Θ(n)f(n) = \Theta(n). Since logba=log22=1\log_b a = \log_2 2 = 1, we get f(n)=Θ(n1)=Θ(nlogba)f(n) = \Theta(n^{1}) = \Theta(n^{\log_b a}), which is case 2. Hence T(n)=Θ(nlogn)T(n) = \Theta(n\log n).

(b) Binary search. For T(n)=T(n/2)+Θ(1)T(n) = T(n/2) + \Theta(1) we have a=1a = 1, b=2b = 2, f(n)=Θ(1)f(n) = \Theta(1). Since log21=0\log_2 1 = 0, we get nlogba=n0=1n^{\log_b a} = n^{0} = 1 and f(n)=Θ(1)=Θ(nlogba)f(n) = \Theta(1) = \Theta(n^{\log_b a}). Again case 2 applies, so T(n)=Θ(n0logn)=Θ(logn)T(n) = \Theta(n^{0}\log n) = \Theta(\log n).

(c) Strassen’s matrix multiplication. For T(n)=7T(n/2)+Θ(n2)T(n) = 7\,T(n/2) + \Theta(n^{2}) we have a=7a = 7, b=2b = 2, f(n)=Θ(n2)f(n) = \Theta(n^{2}). Since log27=2.8073\log_2 7 = 2.8073\ldots, taking ε=0.5\varepsilon = 0.5 gives nlog270.5=n2.307n^{\log_2 7 - 0.5} = n^{2.307\ldots}, and n2=O(n2.307)n^{2} = O(n^{2.307\ldots}) holds. Thus case 1 applies and T(n)=Θ(nlog27)T(n) = \Theta(n^{\log_2 7}), in particular T(n)=O(n2.808)T(n) = O(n^{2.808}) — an order strictly smaller than the Θ(n3)\Theta(n^{3}) of the naive triple loop.

(d) An instance of case 3. For T(n)=2T(n/2)+n2T(n) = 2\,T(n/2) + n^{2} we have log22=1\log_2 2 = 1, and with ε=1\varepsilon = 1 we get n2=Ω(n1+1)n^{2} = \Omega(n^{1+1}). The regularity condition holds because 2(n/2)2=n2/2cn22\,(n/2)^{2} = n^{2}/2 \le c\,n^{2} with c=1/2<1c = 1/2 < 1. Hence T(n)=Θ(n2)T(n) = \Theta(n^{2}): the cost of the topmost level of the recursion alone determines the total.

All the classes seen so far — Θ(n)\Theta(n), Θ(nlogn)\Theta(n\log n), Θ(n2)\Theta(n^2), Θ(n3)\Theta(n^3) — share the property of being bounded by a polynomial in nn, whereas Θ(2n)\Theta(2^n) and Θ(n!)\Theta(n!) do not. As Example 5.4 showed, this boundary cannot be moved by improving the machine. This motivates the following definition.

Definition 7.1Polynomial-time algorithm

An algorithm AA runs in polynomial time if there is a constant kk with TA(n)=O(nk)T_A(n) = O(n^{k}).

The position that polynomial time is the right definition of “efficient” goes back to Cobham and Edmonds. The definition has the drawback of admitting n100n^{100}, but it is strongly justified on two counts. First, the set of polynomials is closed under addition, multiplication and composition, so combining polynomial-time algorithms as building blocks keeps the result polynomial-time. Second, the distinction does not depend on the details of the computational model: complexity differs only polynomially between the RAM model and Turing machines, so the answer to “is it solvable in polynomial time?” does not change when the model does.

Write P\mathrm{P} for the class of decision problems solvable in polynomial time, and NP\mathrm{NP} for the class of decision problems whose “yes” answers admit a certificate verifiable in polynomial time (Definition 4.1[P≠NP 予想とは何か]). The inclusion PNP\mathrm{P} \subseteq \mathrm{NP} is immediate from the definitions, but whether the reverse inclusion holds has been open since the question was posed in 1971. This is the P vs NP problem, and thousands of problems — including subset sum and the travelling salesman problem — are tied to it in the form “if PNP\mathrm{P} \ne \mathrm{NP}, then this problem has no polynomial-time algorithm”. See What is the P vs NP problem for details.

This is where the point of learning complexity notation lies. The OO notation is at once a tool for measuring the speed of individual programs and the common language in which one discusses what can and cannot be computed.

Exercise 8.1Easy

Let f(n)=3n2+5nlog2n+100f(n) = 3n^{2} + 5n\log_2 n + 100. Show that fΘ(n2)f \in \Theta(n^{2}) by exhibiting explicit constants cc and n0n_0 as in Definition 3.1.

Solution

Upper bound. For n2n \ge 2 we have log2nn\log_2 n \le n, so 5nlog2n5n25n\log_2 n \le 5n^{2}. Also 100n2100 \le n^{2} for n10n \ge 10. Hence for n10n \ge 10,

f(n)3n2+5n2+n2=9n2,f(n) \le 3n^{2} + 5n^{2} + n^{2} = 9n^{2} ,

so fO(n2)f \in O(n^{2}) with c2=9c_2 = 9 and n0=10n_0 = 10.

Lower bound. Since 5nlog2n05n\log_2 n \ge 0 for n1n \ge 1 and 100>0100 > 0, we have f(n)3n2f(n) \ge 3n^{2} for every n1n \ge 1. Hence fΩ(n2)f \in \Omega(n^{2}) with c1=3c_1 = 3 and n0=1n_0 = 1.

Combining the two, fΘ(n2)f \in \Theta(n^{2}) with c1=3c_1 = 3, c2=9c_2 = 9, n0=10n_0 = 10. Incidentally, the inequality log2nn\log_2 n \le n (for n1n \ge 1) is also guaranteed by log2no(n)\log_2 n \in o(n), which follows from the first claim of Theorem 4.2; but here it comes directly from 2nn2^{n} \ge n for n2n \ge 2 (by induction on nn: 22=422^{2} = 4 \ge 2, and if 2nn2^{n} \ge n then 2n+1=22n2nn+12^{n+1} = 2\cdot 2^{n} \ge 2n \ge n+1).

Exercise 8.2Standard

Show that log2(n!)Θ(nlogn)\log_2(n!) \in \Theta(n\log n). Do not use Stirling’s formula.

Solution

Upper bound. Since n!=i=1nii=1nn=nnn! = \prod_{i=1}^{n} i \le \prod_{i=1}^{n} n = n^{n}, taking log2\log_2 of both sides (which is increasing) gives

log2(n!)log2(nn)=nlog2n.\log_2(n!) \le \log_2(n^{n}) = n\log_2 n .

Hence log2(n!)O(nlogn)\log_2(n!) \in O(n\log n) with c=1c = 1 and n0=1n_0 = 1.

Lower bound. Let n2n \ge 2 and keep only the larger half of the factors. There are at least n/2n/2 indices ii with in/2i \ge \lceil n/2\rceil, and each such factor is at least n/2n/2, so

n!i=n/2ni(n2)n/2.n! \ge \prod_{i=\lceil n/2\rceil}^{n} i \ge \left(\frac{n}{2}\right)^{n/2} .

Taking log2\log_2,

log2(n!)n2(log2n1).\log_2(n!) \ge \frac{n}{2}\left(\log_2 n - 1\right) .

For n4n \ge 4 we have log2n2\log_2 n \ge 2, so log2n1log2n12log2n=12log2n\log_2 n - 1 \ge \log_2 n - \frac{1}{2}\log_2 n = \frac{1}{2}\log_2 n. Hence

log2(n!)n4log2n(n4),\log_2(n!) \ge \frac{n}{4}\log_2 n \qquad (n \ge 4) ,

giving log2(n!)Ω(nlogn)\log_2(n!) \in \Omega(n\log n) with c=1/4c = 1/4 and n0=4n_0 = 4. Together we obtain Θ(nlogn)\Theta(n\log n).

This estimate is used in proving the Ω(nlogn)\Omega(n\log n) lower bound on the worst-case number of comparisons in comparison sorting (Theorem 6.1[Sorting Algorithms]).

Exercise 8.3Standard

Solve the recurrence T(1)=1T(1) = 1, T(n)=3T(n/4)+nlog2nT(n) = 3\,T(n/4) + n\log_2 n (with nn a power of 44). State explicitly which case of Theorem 6.1 applies and whether the regularity condition is satisfied.

Solution

Here a=3a = 3, b=4b = 4, f(n)=nlog2nf(n) = n\log_2 n. First compute logba=log43=0.7924\log_b a = \log_4 3 = 0.7924\ldots.

Which case. Taking ε=0.2\varepsilon = 0.2 gives log43+ε=0.9924<1\log_4 3 + \varepsilon = 0.9924\ldots < 1. For n2n \ge 2 we have log2n1\log_2 n \ge 1, so f(n)=nlog2nnn0.9925f(n) = n\log_2 n \ge n \ge n^{0.9925}, and therefore f(n)=Ω(nlog43+ε)f(n) = \Omega(n^{\log_4 3 + \varepsilon}). Thus the first condition of case 3 is met.

Regularity condition. For n=4kn = 4^{k} with k1k \ge 1,

af(n/b)=3n4log2n4=34n(log2n2)34nlog2n=34f(n).a\,f(n/b) = 3\cdot\frac{n}{4}\log_2\frac{n}{4} = \frac{3}{4}\,n\left(\log_2 n - 2\right) \le \frac{3}{4}\,n\log_2 n = \frac{3}{4}\,f(n) .

We may take c=3/4<1c = 3/4 < 1, so the regularity condition holds (the inequality log2n2log2n\log_2 n - 2 \le \log_2 n follows from 20-2 \le 0).

Conclusion. By case 3 of Theorem 6.1, T(n)=Θ(f(n))=Θ(nlogn)T(n) = \Theta(f(n)) = \Theta(n\log n). The branching factor 33 loses to the shrinking factor 44, so the cost of the topmost level alone determines the total.

Exercise 8.4Hard

Construct an explicit pair of nonnegative functions f,gf, g with fO(g)f \notin O(g) and gO(f)g \notin O(f), and prove it. This example shows that the hypothesis of Proposition 3.3 — the existence of the limit — is essential.

Solution

Construction. Define functions on N\mathbb{N} by

f(n)={n2(n even)n(n odd)g(n)={n(n even)n2(n odd)f(n) = \begin{cases} n^{2} & (n \text{ even}) \\ n & (n \text{ odd}) \end{cases} \qquad g(n) = \begin{cases} n & (n \text{ even}) \\ n^{2} & (n \text{ odd}) \end{cases}

Both are nonnegative.

Proof that fO(g)f \notin O(g). Suppose fO(g)f \in O(g). Then there are c>0c > 0 and n0n_0 such that f(n)cg(n)f(n) \le c\,g(n) for every nn0n \ge n_0. Choose an even nn with nmax(n0,c+1)n \ge \max(n_0, \lceil c \rceil + 1) (such an even number exists). For this nn we have f(n)=n2f(n) = n^{2} and g(n)=ng(n) = n, so the inequality reads n2cnn^{2} \le c\,n, that is ncn \le c. But nc+1>cn \ge \lceil c\rceil + 1 > c, a contradiction. Hence fO(g)f \notin O(g).

Proof that gO(f)g \notin O(f). Run exactly the same argument with odd numbers in place of even ones. Assuming gO(f)g \in O(f), take c,n0c, n_0 and an odd nmax(n0,c+1)n \ge \max(n_0, \lceil c\rceil + 1); then g(n)=n2g(n) = n^{2} and f(n)=nf(n) = n, so ncn \le c, a contradiction.

Relation to the limit. The ratio f(n)/g(n)f(n)/g(n) equals nn for even nn and 1/n1/n for odd nn, so it oscillates as nn \to \infty and has no limit. Since Proposition 3.3 assumes the existence of the limit, it does not apply to this example. The lesson of the exercise is that the ordering by OO notation is not a total order.

  1. T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022 — Chapter 3 (asymptotic notation) and Chapter 4 (divide and conquer, recurrences, and the floor-function form of the master theorem).
  2. D. E. Knuth, “Big Omicron and big Omega and big Theta”, ACM SIGACT News 8 (1976), 18–24. DOI: 10.1145/1008328.1008329 — the paper that systematised the use of OO, Ω\Omega and Θ\Theta for computer science.
  3. D. E. Knuth, The Art of Computer Programming, Volume 1: Fundamental Algorithms, 3rd ed., Addison-Wesley, 1997 — Section 1.2.11 (asymptotic representations).
  4. R. L. Graham, D. E. Knuth, O. Patashnik, Concrete Mathematics, 2nd ed., Addison-Wesley, 1994 — Chapter 9 (Asymptotics), with a detailed treatment of the techniques of asymptotic expansion.
  5. J. Kleinberg, É. Tardos, Algorithm Design, Addison-Wesley, 2005 — Chapter 2 (the basics of algorithm analysis and the standard complexity classes).
  6. M. R. Garey, D. S. Johnson, Computers and Intractability: A Guide to the Theory of NP-Completeness, W. H. Freeman, 1979 — Chapter 1, which contains a table contrasting polynomial and exponential time against improvements in machine speed.

Appendix: When the master theorem does not apply

Section titled “Appendix: When the master theorem does not apply”

Theorem 6.1 was stated for nn a power of bb. Actual recurrences involve floor functions, and the shape of the splitting sometimes falls outside the scope of the master theorem. In such cases the substitution method — guess the answer and verify it by induction — is available. We illustrate it on the exact recurrence for merge sort.

Define T(1)=1T(1) = 1 and T(n)=2T(n/2)+nT(n) = 2\,T(\lfloor n/2\rfloor) + n for n2n \ge 2 (real merge sort splits into n/2\lfloor n/2 \rfloor and n/2\lceil n/2\rceil; we use this simplified form in order to exhibit the technique).

Upper bound. We show T(n)2nlog2nT(n) \le 2n\log_2 n for all n2n \ge 2 by strong induction on nn.

  • n=2n = 2: T(2)=2T(1)+2=4T(2) = 2T(1) + 2 = 4 and 22log22=42\cdot 2\log_2 2 = 4, so T(2)4T(2) \le 4 holds.
  • n=3n = 3: T(3)=2T(1)+3=5T(3) = 2T(1) + 3 = 5 and 23log23=9.502\cdot 3\log_2 3 = 9.50\ldots, so the bound holds.
  • n4n \ge 4: here n/22\lfloor n/2\rfloor \ge 2 and n/2<n\lfloor n/2 \rfloor < n, so the induction hypothesis applies and gives T(n/2)2n/2log2n/2T(\lfloor n/2\rfloor) \le 2\lfloor n/2\rfloor \log_2 \lfloor n/2\rfloor. Using n/2n/2\lfloor n/2\rfloor \le n/2 and the monotonicity of log2\log_2,
T(n)22n2log2n2+n=2n(log2n1)+n=2nlog2nn2nlog2n,T(n) \le 2\cdot 2\cdot\frac{n}{2}\log_2\frac{n}{2} + n = 2n(\log_2 n - 1) + n = 2n\log_2 n - n \le 2n\log_2 n ,

the last inequality following from n>0n > 0.

Hence T(n)=O(nlogn)T(n) = O(n\log n). The essential point is the leftover n-n: the induction went through precisely because of that slack. Had we tried to prove T(n)cnlog2nT(n) \le c\,n\log_2 n with c=1c = 1, the remainder would not have been at most 00 and the induction would not have closed.

Lower bound. We first show that TT is nondecreasing, proving T(n)T(n1)T(n) \ge T(n-1) for n2n \ge 2 by strong induction on nn. For n=2n = 2 we have T(2)=4T(1)=1T(2) = 4 \ge T(1) = 1. For n3n \ge 3 we have n/2(n1)/21\lfloor n/2\rfloor \ge \lfloor (n-1)/2\rfloor \ge 1, so the induction hypothesis (monotonicity of TT at arguments below nn) gives T(n/2)T((n1)/2)T(\lfloor n/2\rfloor) \ge T(\lfloor (n-1)/2\rfloor). Hence

T(n)=2T(n/2)+n2T((n1)/2)+(n1)=T(n1)T(n) = 2T(\lfloor n/2\rfloor) + n \ge 2T(\lfloor (n-1)/2\rfloor) + (n-1) = T(n-1)

(for n=3n = 3 the right-hand side is precisely the defining recurrence for T(2)T(2), and the same holds for n4n \ge 4).

Next we compute the value at nn a power of two, n=2kn = 2^{k}. From T(2k)=2T(2k1)+2kT(2^{k}) = 2T(2^{k-1}) + 2^{k} and T(1)=1T(1) = 1, induction on kk gives T(2k)=2k(k+1)T(2^{k}) = 2^{k}(k+1). Indeed, for k=0k = 0 we have 20(0+1)=1=T(1)2^{0}(0+1) = 1 = T(1), and if the formula holds for k1k-1 then

T(2k)=22k1k+2k=2kk+2k=2k(k+1).T(2^{k}) = 2\cdot 2^{k-1}k + 2^{k} = 2^{k}k + 2^{k} = 2^{k}(k+1) .

For general n1n \ge 1 put m=2log2nm = 2^{\lfloor \log_2 n\rfloor}, so that mnm \le n and m>n/2m > n/2. By monotonicity,

T(n)T(m)=m(log2n+1)>n2log2nT(n) \ge T(m) = m\left(\lfloor\log_2 n\rfloor + 1\right) > \frac{n}{2}\log_2 n

(using log2n+1>log2n\lfloor \log_2 n\rfloor + 1 > \log_2 n). Hence T(n)=Ω(nlogn)T(n) = \Omega(n\log n), and together with the upper bound, T(n)=Θ(nlogn)T(n) = \Theta(n\log n).

The key to the substitution method is to fix the exact form to be proved before starting the induction. Assuming only an order such as O(nlogn)O(n\log n) and inducting leads to the classic error in which the constant grows at every step and diverges. Write the bound out with its constants, as in T(n)2nlog2nT(n) \le 2n\log_2 n, and check that the induction step preserves the same constant.

Report an error in this article ・Operated by: Mugen Giken LLCPricingTermsLegal notice

© 2026 夢現技研合同会社 ・Feeding the text to an LLM is welcome. Code samples are MIT licensed.