Complexity

Let g(n) be a function on natural numbers. g(n) is eventually positive if g(n) > 0 for all n ³ some fixed integer. We'll only consider eventually positive functions in this course. Define O(g(n)) to be the set of all functions f(n) on natural numbers n such that there exist constant c > 0 and integer n0 ³ 0 such that
n ³ n0 Þ f(n) £ cg(n).
In other words, f(n) is in O(g(n)) if and only if f(n) is bounded above by a constant multiple of g(n) for sufficiently large n. If f(n) is in O(g(n)), then we either write
f(n) Î O(g(n)), or f(n) = O(g(n)).
Note that the latter is an abuse of the equality notation. We write g(n) = W(f(n)) iff f(n) = O(g(n)). In this case, we say ``f(n) is of order at most g(n)", and ``g(n) is of order at least f(n)". One can also say ``g(n) is an asymptotic upper bound of f(n)" and ``f(n) is an asymptotic lower bound of g(n)."

Examples:
10n2
=
O(n3)
10n2
=
O(nk),    "k ³ 2
[n5+1] / [n2-2]
=
O(n3)
|sin n|
=
O(1)
|n cos n|
=
O(n)
Define Q(g(n)) to be the set of all functions f(n) on natural numbers such that
f(n) = O(g(n)) and g(n) = O(f(n)).
These conditions can be restated as: there exist constants c1, c2 > 0 and integer n0 ³ 0 such that
n ³ n0 Þ c1 g(n) £ f(n) £ c2 g(n).
In other words, f(n) is in Q(g(n)) if and only if f(n) is bounded between two constant multiples of g(n) for sufficiently large n.
If f(n) is in Q(g(n)), then we can either write
f(n) Î Q(g(n)), or f(n) = Q(g(n)).
We say that ``f(n) and g(n) have the same order," or g(n) is an asymptotically tight bound of f(n)." It is easily seen that f(n) = Q(g(n)) Þ f(n) = O(g(n)) but not conversely.

Examples:
10n2
=
Q(n2)
[n5+1] / [n2-2]
=
Q(n3)
ln n
=
Q(lg n)
100n2log3 n
=
Q(n2 lg3 n)

Basic properties

Hence Q defines an equivalence relation on the set of functions, while O and W each defines a partial ordering on the equivalence classes of Q.

More properties:

There are two less popular notations:
o(g(n)) =: {f(n):f(n)=O(g(n)) but f(n) ¹ Q(g(n))}.

w(g(n)) =: {f(n):f(n)=W(g(n)) but f(n) ¹ Q(g(n))}.
We have the following analogy between ``=" and the asymptotic comparison of two functions:
f(n) = O(g(n))
«
a £ b
f(n) = W(g(n))
«
a ³ b
f(n) = Q(g(n))
«
a = b
f(n) = o(g(n))
«
a < b
f(n) = w(g(n))
«
a > b
Stirling's approximation:
n! =
Ö
 

2pn
 
( n / e)n(1 + Q(1 / n)),
which imples that

lim
n ® ¥ 
log(n!) / (n logn) = 1.
L'Hôpital's rule

If limx ® af(x)=0=limx ® ag(x) or limx ® af(x)=¥ = limx ® ag(x),then

lim
x ® a 
f(x) / g(x) =
lim
x ® a 
f¢(x) / g¢(x)
provided the latter limit exists.

Comparison by limits

If c = limn ® ¥[f(n) / g(n)],then

The following are some useful facts about elementary functions:

Recurrence relation

A recurrence relation for a function is an equation or inequality that describes the function in terms of its values on smaller inputs. Examples are:

  1. Fibonacci sequence f(0) = 1, f(1) = 1,
    f(n) = f(n-1) + f(n-2), for n > 1.
  2. Towers of Hanoi C(1) = 1,
    C(n) = 2C(n-1) + 1, for n > 1.
  3. Binary Search T(1) = Q(1),
    T(n) = T(ën/2 û) + Q(1), for n > 1.
Methods for solving recurrence relations exactly:

  1. Induction. Guess the solution from some terms and prove the guess by mathematical induction.
  2. Iteration. Repeatedly expand the recurrence and express the result (usually) as a summation of terms. Finally find a closed-form expression for the summation.
  3. Generating Function. Determine mathematically the function
    F(z) =: ¥
    å
    n=0 
    f(n)zn.
    Then
    f(n) = ( 1 / n!) F(n)(0).
  4. Formula. Only special recurrences have formulas for their solutions, e.g. linear homogeneous recurrence with constant coefficients.
In this course, recurrence is mostly used in expressing the running time of algorithms. It only requires to solve a recurrence asymptotically, i.e. expressing the solution as O(g(n)), Q(g(n)), or W(g(n)), depending on the application, for some well known function g(n). That means, we want to bound the function from above and/or from below by some simple functions. When O- and W -notations are used, we always require that the bounds are as tight as possible. The induction and iteration methods can also be adopted to solve recurrences asymptotically. [Master theorem] Let a ³ 1, b > 1 and c > 0 be constants, let f(n) be a function, and let T(n) be defined by
ì
í
î
T(1) = c,
T(n) = aT(n/b) + f(n),    n > 1
where we interprete n/b to mean either ën/b û or én/b ù. Then T(n) can be solved asymptotically as

  1. If f(n) = O(nlogba- e) for some constant e > 0, then T(n) = Q(nlogba).
  2. If f(n) = Q(nlogba), then T(n) = Q(nlogbalgn).
  3. If f(n) = W(nlogba+e) for some constant e > 0, and if af(n/b) £ cf(n) for some constant c < 1 and all sufficiently large n, then T(n) = Q(f(n)).
Examples:

  1. T(n) = 4T(n/2) + n Þ T(n) = Q(n2).
  2. T(n) = 9T(n/3) + O(n) Þ T(n) = Q(n2).
  3. T(n) = 2T(n/2) + Q(n) Þ T(n) = Q(n lgn).
  4. T(n) = 4T(n/2) + n2 Þ T(n) = Q(n2lgn).
  5. T(n) = 4T(n/2) + n3 Þ T(n) = Q(n3).