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)≤c g(n)f(n) \le c\,g(n) for every n≥n0n \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 1≺log⁡n≺nε≺n≺nlog⁡n≺n2≺2n≺n!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 takes 2n2^{n} times as long as before. 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)=a T(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 nlog⁡2nn\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 nlog⁡nn\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.1(The 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(log⁡n)O(\log n) bits, where nn is the input size.

The last condition is easy to overlook but essential. Without the restriction to O(log⁡n)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 log⁡2n\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.3(Worst-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)=max⁡∣x∣=ntA(x),SA(n)=max⁡∣x∣=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.4(Space 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.5(Counting 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=i−1,i−2,…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 j≥0j \ge 0, that is, at most ii. This bound is attained exactly when the input is the strictly decreasing sequence a=(n,n−1,…,1)a = (n, n-1, \ldots, 1). Indeed, then key is always smaller than every element of a[0..i−1]a[0..i-1], so the while runs until j=−1j = -1, giving ii comparisons at j=i−1,…,0j = i-1, \ldots, 0. Hence the worst-case number of comparisons is

∑i=1n−1i=n(n−1)2.\sum_{i=1}^{n-1} i = \frac{n(n-1)}{2} .

For the same input the number of assignments is ∑i=1n−1(i+2)=n(n−1)2+2(n−1)\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 n−1n-1 comparisons, that is Θ(n)\Theta(n). Quicksort is Θ(n2)\Theta(n^2) in the worst case yet Θ(nlog⁡n)\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.1(The 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, ∃n0∈N, ∀n≥n0, f(n)≤c g(n) }Ω(g)={ f  :  ∃c>0, ∃n0∈N, ∀n≥n0, f(n)≥c g(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 f∈O(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 f∈O(g)f \in O(g) holds for arbitrary ff and gg (with g>0g > 0), and the notation becomes vacuous.

What the definition of O notation asserts

The notations oo and ω\omega strengthen one quantifier.

Definition 3.2(The notations o and ω)

o(g)={ f  :  ∀c>0, ∃n0∈N, ∀n≥n0, f(n)≤c g(n) }ω(g)={ f  :  ∀c>0, ∃n0∈N, ∀n≥n0, f(n)≥c g(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 f∈o(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.3(The limit test)

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

  1. If 0≤L<∞0 \le L < \infty then f∈O(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 f∈o(g)f \in o(g).
  4. If L=∞L = \infty then f∈ω(g)f \in \omega(g) and g∈o(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 n≥n1n \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 f∈O(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)>L−L/2=L/2f(n)/g(n) > L - L/2 = L/2 for n≥n2n \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)≤c g(n)f(n) \le c\,g(n), for n≥n0n \ge n_0. As cc was arbitrary, Definition 3.2 gives f∈o(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)≥c g(n)f(n) \ge c\,g(n), for n≥n0n \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 g∈o(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.4(Rules 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) f∈O(f)f \in O(f).
  2. (Transitivity) If f∈O(g)f \in O(g) and g∈O(h)g \in O(h) then f∈O(h)f \in O(h).
  3. (Scalar multiples) If λ>0\lambda > 0 and f∈O(g)f \in O(g) then λf∈O(g)\lambda f \in O(g).
  4. (Sums) If f1∈O(g1)f_1 \in O(g_1) and f2∈O(g2)f_2 \in O(g_2) then f1+f2∈O(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 f1∈O(g1)f_1 \in O(g_1) and f2∈O(g2)f_2 \in O(g_2) then f1f2∈O(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)≤1⋅f(n)f(n) \le 1 \cdot f(n) for every n≥1n \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 n≥n1n \ge n_1, and c2>0,n2c_2 > 0, n_2 with g(n)≤c2h(n)g(n) \le c_2 h(n) for n≥n2n \ge n_2. For n≥max⁡(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)≤c g(n)f(n) \le c\,g(n) for n≥n0n \ge n_0, multiplying by λ>0\lambda > 0 gives λf(n)≤λc g(n)\lambda f(n) \le \lambda c\,g(n). Replace the constant by λc\lambda c.

  4. For n≥max⁡(n1,n2)n \ge \max(n_1,n_2), using gi≤max⁡(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 n≥max⁡(n1,n2)n \ge \max(n_1,n_2), since f1,f2,g1,g2≥0f_1, f_2, g_1, g_2 \ge 0 the two inequalities may be multiplied, giving f1(n)f2(n)≤c1c2 g1(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(nlog⁡n)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.5(The order of a polynomial)

Let d≥0d \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=0d∣ai∣A = \sum_{i=0}^{d} |a_i|. For n≥1n \ge 1 we have ni≤ndn^i \le n^d for 0≤i≤d0 \le i \le d, so

p(n)≤∑i=0d∣ai∣ ni≤(∑i=0d∣ai∣)nd=A nd.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 p∈O(nd)p \in O(n^d) with c=Ac = A and n0=1n_0 = 1.

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

p(n)=nd(ad+∑i=0d−1aini−d),∣∑i=0d−1aini−d∣≤∑i=0d−1∣ai∣ ni−d≤Bn,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 ni−d≤n−1n^{i-d} \le n^{-1}, valid since i≤d−1i \le d-1. Taking n0=⌈2B/ad⌉+1n_0 = \lceil 2B/a_d \rceil + 1, we have B/n≤ad/2B/n \le a_d/2 for n≥n0n \ge n_0, whence

p(n)≥nd(ad−ad2)=ad2 nd.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 log⁡an=log⁡bn/log⁡ba\log_a n = \log_b n / \log_b a, the functions log⁡an\log_a n and log⁡bn\log_b n differ only by a positive constant factor, so Θ(log⁡an)=Θ(log⁡bn)\Theta(\log_a n) = \Theta(\log_b n). However, as 2log⁡2n=n2^{\log_2 n} = n versus 2log⁡10n=n0.301…2^{\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 ”log⁡n\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.1(Exponentials beat polynomials)

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

lim⁡x→∞xkc x=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=c−1>0h = c - 1 > 0. Put m=⌈k⌉+1m = \lceil k \rceil + 1, so that m>km > k. By the binomial theorem, for n≥mn \ge m,

c n=(1+h)n≥(nm)hm=n(n−1)⋯(n−m+1)m! hm≥(n−m+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,n−1,…,n−m+1n, n-1, \ldots, n-m+1 is at least the smallest one, n−m+1n-m+1). If moreover n≥2mn \ge 2m, then n−m+1>n−m≥n/2n - m + 1 > n - m \ge n/2, so

nkc n≤m!  nkhm(n/2)m=m! 2mhm  n k−m.\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 k−mk - m is negative and the right-hand side tends to 00 as n→∞n \to \infty. As nk/cn≥0n^k/c^n \ge 0, the squeeze theorem gives lim⁡n→∞nk/cn=0\lim_{n\to\infty} n^k/c^n = 0.

Now the real variable case. For x≥1x \ge 1 put n=⌊x⌋+1n = \lfloor x \rfloor + 1, so that x≤nx \le n and n−1≤xn - 1 \le x. Since k≥0k \ge 0 and c>1c > 1,

xkc x≤nkc n−1=c⋅nkc n.\frac{x^k}{c^{\,x}} \le \frac{n^k}{c^{\,n-1}} = c\cdot\frac{n^k}{c^{\,n}} .

As x→∞x \to \infty we have n→∞n \to \infty, and by the previous paragraph the right-hand side tends to 00. Hence lim⁡x→∞xk/cx=0\lim_{x\to\infty} x^k/c^x = 0.

Theorem 4.2(The hierarchy of growth rates)

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

(log⁡2n)a∈o(nε),nk∈o(c n),c n∈o(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 log⁡2n\log_2 n, nn, 2n2^n, n!n! are of strictly increasing order in this sequence.

Proof(Theorem 4.2)

First claim. Put t=log⁡2nt = \log_2 n, so that n=2tn = 2^t and t→∞t \to \infty as n→∞n \to \infty. Then

(log⁡2n)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, (log⁡2n)a∈o(nε)(\log_2 n)^a \in o(n^{\varepsilon}).

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

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

c nn!=c mm!∏j=m+1ncj.\frac{c^{\,n}}{n!} = \frac{c^{\,m}}{m!}\prod_{j=m+1}^{n} \frac{c}{j} .

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

0≤c nn!≤c mm!(12)n−m,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 n→∞n \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, cn∈o(n!)c^n \in o(n!).

The first claim says that however small ε>0\varepsilon > 0 is chosen, nεn^{\varepsilon} eventually exceeds (log⁡n)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²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.1(The 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)=αlog⁡2n+β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)=αnlog⁡2nT(n) = \alpha n \log_2 n then T(2n)/T(n)=2(1+1log⁡2n)T(2n)/T(n) = 2\left(1 + \dfrac{1}{\log_2 n}\right), which tends to 22 as n→∞n \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)=α(log⁡22n−log⁡2n)+(β−β)=αlog⁡22=α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)=α⋅2nlog⁡22nα nlog⁡2n=2⋅log⁡2n+1log⁡2n=2(1+1log⁡2n)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 n→∞n \to \infty we have 1/log⁡2n→01/\log_2 n \to 0, so the ratio tends to 22.
  5. T(2n)/T(n)=α22n/(α2n)=22n−n=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 240≈1.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+sin⁡n)T(n) = n\,(2 + \sin n). Since 1≤2+sin⁡n≤31 \le 2+\sin n \le 3 we have T∈Θ(n)T \in \Theta(n), yet T(2n)/T(n)=2(2+sin⁡2n)/(2+sin⁡n)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.3(Operation counts and running times in practice)

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

nnlog⁡2n\log_2 nnnnlog⁡2nn\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
nlog⁡2nn\log_2 n0.020.02 s3030 s
n2n^21717 min3232 years

Look at the nlog⁡2nn\log_2 n row. Even at n=109n = 10^9 the factor log⁡2n\log_2 n is only 3030, so nlog⁡nn\log n is at most thirty times nn. Over the range of realistic input sizes, Θ(nlog⁡n)\Theta(n\log n) is barely distinguishable from Θ(n)\Theta(n). This is why Θ(nlog⁡n)\Theta(n\log n) algorithms such as comparison sorting and the fast Fourier transform are treated as “essentially linear”. The same applies to Θ(log⁡n)\Theta(\log n): as nn grows a hundred-million-fold from 1010 to 10910^9, the value of log⁡2n\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 250≈1.1×10152^{50} \approx 1.1\times10^{15} operations takes about 1313 days, and 2100≈1.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.4(What 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
nlog⁡2nn\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=log⁡2tn = \log_2 t, so multiplying tt by 10001000 increases nn by log⁡21000=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 log⁡c1000\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.5(From 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 Θ(2n⋅n)\Theta(2^n \cdot n). For n=40n = 40 this is 240×40≈4.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 a hundred 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 log⁡2W\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)Θ(log⁡n)\Theta(\log n)Θ(n)\Theta(n)Θ(log⁡n)\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)Θ(log⁡n)\Theta(\log n)avg. Θ(1)\Theta(1)
deletionΘ(n)\Theta(n) (search included)Θ(n)\Theta(n)Θ(1)\Theta(1) (position known)Θ(log⁡n)\Theta(\log n)avg. Θ(1)\Theta(1)
retrieval of the minimumΘ(n)\Theta(n)Θ(1)\Theta(1)Θ(n)\Theta(n)Θ(log⁡n)\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+1−1<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)=2 T(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.1(The master theorem)

Let a≥1a \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)=a T(n/b)+f(n)(n=bk, k≥1).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 ⁣(nlog⁡ba−ε)f(n) = O\!\left(n^{\log_b a - \varepsilon}\right) for some ε>0\varepsilon > 0, then T(n)=Θ ⁣(nlog⁡ba)T(n) = \Theta\!\left(n^{\log_b a}\right).
  2. If f(n)=Θ ⁣(nlog⁡ba)f(n) = \Theta\!\left(n^{\log_b a}\right), then T(n)=Θ ⁣(nlog⁡balog⁡n)T(n) = \Theta\!\left(n^{\log_b a}\log n\right).
  3. If f(n)=Ω ⁣(nlog⁡ba+ε)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 a f(bk−1)≤c f(bk)a\,f(b^{k-1}) \le c\,f(b^{k}) for all k≥1k \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=0k−1ajf ⁣(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=alog⁡bn=(blog⁡ba)log⁡bn=(blog⁡bn)log⁡ba=nlog⁡ba,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 d nlog⁡bad\,n^{\log_b a}. Since f>0f > 0, we always have T(n)≥d nlog⁡baT(n) \ge d\,n^{\log_b a}. It remains to estimate the sum Σ=∑j=0k−1ajf(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)≤C mlog⁡ba−εf(m) \le C\,m^{\log_b a - \varepsilon} for all sufficiently large powers mm of bb. Then

Σ≤C∑j=0k−1aj(nbj)log⁡ba−ε=C nlog⁡ba−ε∑j=0k−1aj b−j(log⁡ba−ε).\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 b−jlog⁡ba=a−jb^{-j\log_b a} = a^{-j}, we have ajb−j(log⁡ba−ε)=(bε)ja^{j} b^{-j(\log_b a - \varepsilon)} = (b^{\varepsilon})^{j}, and the formula for a geometric series gives

∑j=0k−1(bε)j=bεk−1bε−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ε−1 nlog⁡ba\Sigma < \dfrac{C}{b^{\varepsilon}-1}\,n^{\log_b a} and T(n)=O(nlog⁡ba)T(n) = O(n^{\log_b a}). The lower bound is the inequality T(n)≥d nlog⁡baT(n) \ge d\,n^{\log_b a} noted above, so together T(n)=Θ(nlog⁡ba)T(n) = \Theta(n^{\log_b a}).

Case 2. By hypothesis there are c1,c2>0c_1, c_2 > 0 with c1mlog⁡ba≤f(m)≤c2mlog⁡bac_1 m^{\log_b a} \le f(m) \le c_2 m^{\log_b a}. Since aj(n/bj)log⁡ba=ajnlog⁡baa−j=nlog⁡baa^{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 c1nlog⁡bac_1 n^{\log_b a} and c2nlog⁡bac_2 n^{\log_b a}. There are k=log⁡bnk = \log_b n terms, so

c1 nlog⁡balog⁡bn≤Σ≤c2 nlog⁡balog⁡bn.c_1\,n^{\log_b a} \log_b n \le \Sigma \le c_2\,n^{\log_b a}\log_b n .

As log⁡bn\log_b n and log⁡n\log n differ only by a positive constant factor (Remark 3.7), Σ=Θ(nlog⁡balog⁡n)\Sigma = \Theta(n^{\log_b a}\log n). The first term d nlog⁡bad\,n^{\log_b a} is absorbed into this, so T(n)=Θ(nlog⁡balog⁡n)T(n) = \Theta(n^{\log_b a}\log n).

Case 3. From the regularity condition one proves ajf(n/bj)≤c jf(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)=aj⋅af(n/bj+1)≤aj c f(n/bj)≤c⋅c jf(n)=c j+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=0k−1c j<f(n)1−c.\Sigma \le f(n) \sum_{j=0}^{k-1} c^{\,j} < \frac{f(n)}{1-c} .

Moreover, the hypothesis f(n)=Ω(nlog⁡ba+ε)f(n) = \Omega(n^{\log_b a + \varepsilon}) gives a c3>0c_3 > 0 such that nlog⁡ba≤f(n)c3 nε≤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)=a T(⌊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 log⁡bn0+1\log_b n_0 + 1 terms violate the condition and each of them is O(nlog⁡ba)=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.3(Applying the master theorem)

(a) Merge sort. For T(n)=2 T(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 log⁡ba=log⁡22=1\log_b a = \log_2 2 = 1, we get f(n)=Θ(n1)=Θ(nlog⁡ba)f(n) = \Theta(n^{1}) = \Theta(n^{\log_b a}), which is case 2. Hence T(n)=Θ(nlog⁡n)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 log⁡21=0\log_2 1 = 0, we get nlog⁡ba=n0=1n^{\log_b a} = n^{0} = 1 and f(n)=Θ(1)=Θ(nlog⁡ba)f(n) = \Theta(1) = \Theta(n^{\log_b a}). Again case 2 applies, so T(n)=Θ(n0log⁡n)=Θ(log⁡n)T(n) = \Theta(n^{0}\log n) = \Theta(\log n).

(c) Strassen’s matrix multiplication. For T(n)=7 T(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 log⁡27=2.8073…\log_2 7 = 2.8073\ldots, taking ε=0.5\varepsilon = 0.5 gives nlog⁡27−0.5=n2.307…n^{\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)=Θ(nlog⁡27)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)=2 T(n/2)+n2T(n) = 2\,T(n/2) + n^{2} we have log⁡22=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/2≤c n22\,(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), Θ(nlog⁡n)\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.1(Polynomial-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 P⊆NP\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 P≠NP\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+5nlog⁡2n+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 n≥2n \ge 2 we have log⁡2n≤n\log_2 n \le n, so 5nlog⁡2n≤5n25n\log_2 n \le 5n^{2}. Also 100≤n2100 \le n^{2} for n≥10n \ge 10. Hence for n≥10n \ge 10,

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

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

Lower bound. Since 5nlog⁡2n≥05n\log_2 n \ge 0 for n≥1n \ge 1 and 100>0100 > 0, we have f(n)≥3n2f(n) \ge 3n^{2} for every n≥1n \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 log⁡2n≤n\log_2 n \le n (for n≥1n \ge 1) is also guaranteed by log⁡2n∈o(n)\log_2 n \in o(n), which follows from the first claim of Theorem 4.2; but here it comes directly from 2n≥n2^{n} \ge n for n≥2n \ge 2 (by induction on nn: 22=4≥22^{2} = 4 \ge 2, and if 2n≥n2^{n} \ge n then 2n+1=2⋅2n≥2n≥n+12^{n+1} = 2\cdot 2^{n} \ge 2n \ge n+1).

Exercise 8.2Standard

Show that log⁡2(n!)∈Θ(nlog⁡n)\log_2(n!) \in \Theta(n\log n). Do not use Stirling’s formula.

Solution

Upper bound. Since n!=∏i=1ni≤∏i=1nn=nnn! = \prod_{i=1}^{n} i \le \prod_{i=1}^{n} n = n^{n}, taking log⁡2\log_2 of both sides (which is increasing) gives

log⁡2(n!)≤log⁡2(nn)=nlog⁡2n.\log_2(n!) \le \log_2(n^{n}) = n\log_2 n .

Hence log⁡2(n!)∈O(nlog⁡n)\log_2(n!) \in O(n\log n) with c=1c = 1 and n0=1n_0 = 1.

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

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

Taking log⁡2\log_2,

log⁡2(n!)≥n2(log⁡2n−1).\log_2(n!) \ge \frac{n}{2}\left(\log_2 n - 1\right) .

For n≥4n \ge 4 we have log⁡2n≥2\log_2 n \ge 2, so log⁡2n−1≥log⁡2n−12log⁡2n=12log⁡2n\log_2 n - 1 \ge \log_2 n - \frac{1}{2}\log_2 n = \frac{1}{2}\log_2 n. Hence

log⁡2(n!)≥n4log⁡2n(n≥4),\log_2(n!) \ge \frac{n}{4}\log_2 n \qquad (n \ge 4) ,

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

This estimate is used in proving the Ω(nlog⁡n)\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)=3 T(n/4)+nlog⁡2nT(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)=nlog⁡2nf(n) = n\log_2 n. First compute log⁡ba=log⁡43=0.7924…\log_b a = \log_4 3 = 0.7924\ldots.

Which case. Taking ε=0.2\varepsilon = 0.2 gives log⁡43+ε=0.9924…<1\log_4 3 + \varepsilon = 0.9924\ldots < 1. For n≥2n \ge 2 we have log⁡2n≥1\log_2 n \ge 1, so f(n)=nlog⁡2n≥n≥n0.9925f(n) = n\log_2 n \ge n \ge n^{0.9925}, and therefore f(n)=Ω(nlog⁡43+ε)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 k≥1k \ge 1,

a f(n/b)=3⋅n4log⁡2n4=34 n(log⁡2n−2)≤34 nlog⁡2n=34 f(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 log⁡2n−2≤log⁡2n\log_2 n - 2 \le \log_2 n follows from −2≤0-2 \le 0).

Conclusion. By case 3 of Theorem 6.1, T(n)=Θ(f(n))=Θ(nlog⁡n)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 f∉O(g)f \notin O(g) and g∉O(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 f∉O(g)f \notin O(g). Suppose f∈O(g)f \in O(g). Then there are c>0c > 0 and n0n_0 such that f(n)≤c g(n)f(n) \le c\,g(n) for every n≥n0n \ge n_0. Choose an even nn with n≥max⁡(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 n2≤c nn^{2} \le c\,n, that is n≤cn \le c. But n≥⌈c⌉+1>cn \ge \lceil c\rceil + 1 > c, a contradiction. Hence f∉O(g)f \notin O(g).

Proof that g∉O(f)g \notin O(f). Run exactly the same argument with odd numbers in place of even ones. Assuming g∈O(f)g \in O(f), take c,n0c, n_0 and an odd n≥max⁡(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 n≤cn \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 n→∞n \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)=2 T(⌊n/2⌋)+nT(n) = 2\,T(\lfloor n/2\rfloor) + n for n≥2n \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)≤2nlog⁡2nT(n) \le 2n\log_2 n for all n≥2n \ge 2 by strong induction on nn.

  • n=2n = 2: T(2)=2T(1)+2=4T(2) = 2T(1) + 2 = 4 and 2⋅2log⁡22=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 2⋅3log⁡23=9.50…2\cdot 3\log_2 3 = 9.50\ldots, so the bound holds.
  • n≥4n \ge 4: here ⌊n/2⌋≥2\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⌋)≤2⌊n/2⌋log⁡2⌊n/2⌋T(\lfloor n/2\rfloor) \le 2\lfloor n/2\rfloor \log_2 \lfloor n/2\rfloor. Using ⌊n/2⌋≤n/2\lfloor n/2\rfloor \le n/2 and the monotonicity of log⁡2\log_2,
T(n)≤2⋅2⋅n2log⁡2n2+n=2n(log⁡2n−1)+n=2nlog⁡2n−n≤2nlog⁡2n,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(nlog⁡n)T(n) = O(n\log n). The essential point is the leftover −n-n: that slack is what pays for the base cases n=2,3n = 2, 3. Had we tried to prove T(n)≤c nlog⁡2nT(n) \le c\,n\log_2 n with c=1c = 1, the induction step itself would still close, if only barely, with remainder (1−c)n=0(1-c)n = 0; what fails is the base case, since T(2)=4>2=1⋅2log⁡22T(2) = 4 > 2 = 1\cdot 2\log_2 2.

Lower bound. We first show that TT is nondecreasing, proving T(n)≥T(n−1)T(n) \ge T(n-1) for n≥2n \ge 2 by strong induction on nn. For n=2n = 2 we have T(2)=4≥T(1)=1T(2) = 4 \ge T(1) = 1. For n≥3n \ge 3 we have ⌊n/2⌋≥⌊(n−1)/2⌋≥1\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(⌊(n−1)/2⌋)T(\lfloor n/2\rfloor) \ge T(\lfloor (n-1)/2\rfloor). Hence

T(n)=2T(⌊n/2⌋)+n≥2T(⌊(n−1)/2⌋)+(n−1)=T(n−1)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 n≥4n \ge 4).

Next we compute the value at nn a power of two, n=2kn = 2^{k}. From T(2k)=2T(2k−1)+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 k−1k-1 then

T(2k)=2⋅2k−1k+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 n≥1n \ge 1 put m=2⌊log⁡2n⌋m = 2^{\lfloor \log_2 n\rfloor}, so that m≤nm \le n and m>n/2m > n/2. By monotonicity,

T(n)≥T(m)=m(⌊log⁡2n⌋+1)>n2log⁡2nT(n) \ge T(m) = m\left(\lfloor\log_2 n\rfloor + 1\right) > \frac{n}{2}\log_2 n

(using ⌊log⁡2n⌋+1>log⁡2n\lfloor \log_2 n\rfloor + 1 > \log_2 n). Hence T(n)=Ω(nlog⁡n)T(n) = \Omega(n\log n), and together with the upper bound, T(n)=Θ(nlog⁡n)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(nlog⁡n)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)≤2nlog⁡2nT(n) \le 2n\log_2 n, and check that the induction step preserves the same constant.

not audited

Report an error in this article ・Operated by: Mugen Giken LLC ・Pricing ・Terms ・Legal notice

© 2026 夢現技研合同会社 ・Code samples are MIT licensed.