Purpose

Running time is roughly proportional to the number of simple operations performed, so counting operations as a function of input size is how we compare algorithms without benchmarking them. This note pins down the three asymptotic notations and the growth-rate facts worth memorizing.

O-Notation

Given two functions and , we say that is if there exist constants and such that for all .

Omega-Notation

Given two functions and , we say that is if there exist constants and such that for all .

Theta-Notation

Given two functions and , we say that is if there exist constants , , and such that for all .

The three bounds

NotationRoleGuarantee for all
upper bound
lower bound
tight boundboth, with separate constants

Common Bounds

Logarithms grow slower than every polynomial with , and every polynomial grows slower than every exponential with .

Polynomial

Logarithmic

Base changes only shift a logarithm by a constant factor, since .

Exponential

Factorial

”Efficient” Algorithms

A single CPU core executes on the order of simple operations per second. That budget makes exponential algorithms useless beyond tiny inputs: operations is decades of compute, and blows past that at .

Polynomial time is the standard bar for an efficient algorithm, and it has a useful scaling property: if the input size grows by a constant factor, the running time of a polynomial time algorithm also grows by a constant factor.