Growth of Functions
The growth of a function is determined by the highest order term: if you add a bunch of terms, the function grows about as fast as the largest term (for large enough input values).
For example, f(x)=x2+1 grows as fast as g(x)=x2+2 and h(x)=x2+x+1, because for large x, x2 is much bigger than 1, 2, or x+1.
Similarly, constant multiples don't matter that much: f(x)=x2 grows as fast as g(x)=2x2 and h(x)=100x2, because for large x, multiplying x2 by a constant does not change it "too much" (at least not as much as increasing x).
Essentially, we are concerned with the shape of the curve:
All three of these functions are lines; their exact slope/y-intercept does not matter.
Only caring about the highest order term (without constant multiples) corresponds to ignoring differences in hardware/operating system/etc. If the CPU is twice as fast, for example, the algorithm still behaves the same way, even if it executes faster.
Big-Oh Notation
Let f and g be functions from Z→R or R→R. We say f(x) is O(g(x)) if there are constants c>0 and k>0 such that 0≤f(n)≤c×g(n) for all x≥k. The constants c and k are called witnesses. We read f(x) is O(g(x)) as "f(x) is big-Oh of g(x)". We write f(x)∈O(g(x)) or f(x)=O(g(x)) (though the former is more technically correct).
Basically, f(x) is O(g(x)) means that, after a certain value of x, f is always smaller than some constant multiple of g:
Here are some examples that use big-Oh notation:
- To show that 5x2+10x+3 is O(x2): 5x2+10x+3≤5x2+10x2+3x2=18x2 Each of the above steps is true for all x≥1, so take c=18, k=1 as witnesses.
- To show that 5x2−10x+3 is O(x2): 5x2−10x+3≤5x2+3≤5x2+3x2=8x2 The first step is true as long as 10x>0 (which is the same as x>0) and the second step is true as long as x≥1, so take c=8, k=1 as witnesses.
-
Is it true that x3 is O(x2)?
Suppose it is true. Then x3≤cx2 for x>k. Dividing through by x2, we get that x≤c. This says that "x is always less than a constant", but this is not true: a line with positive slope is not bounded from above by any constant! Therefore, x3 is not O(x2).
Typically, we want the function inside the Oh to be as small and simple as possible. Even though it is true, for example, that 5x2+10x+3 is O(x3), this is not terribly informative. Similarly, 5x2+10x+3 is O(2x2+11x+3), but this is not particularly useful.
Here are some important big-Oh results:
-
If f(x)=anxn+an−1xn−1+⋯+a1x+a0 where an>0, then f(x) is O(xn).
Proof: If x>1, then: f(x)=anxn+an−1xn−1+⋯+a1x+a0≤|an|xn+|an−1|xn−1+⋯+|a1|x+|a0|≤|an|xn+|an−1|xn+⋯+|a1|xn+|a0|xn=xn(|an|+|an−1|+⋯+|a1|+|a0|) Therefore, take c=|an|+|an−1|+⋯+|a1|+|a0|>0 and k=1.
- What is the sum of the first n integers? 1+2+3+⋯+n≤n+n+n+⋯+n=n×n=n2 Take c=1,k=1 to see that sum is O(n2). Notice that this agrees with the formula we derived earlier: ∑ni=1i=n(n+1)/2, which is O(n2).
- What is the growth of n!? n!=n×(n−1)×(n−2)×⋯×2×1=n×n×n×⋯n=nn Therefore, n! is O(nn) with c=k=1
-
What is the growth of logn!?
Take the logarithm of both sides of the previous equation to get logn!≤lognn, so logn!≤nlogn. Therefore, logn! is O(nlogn) with c=k=1.
-
How does log2n compare to n?
We know that n<2n (we will prove this later). Taking the logarithm of both sides, we have that log2n<log22n=n. So log2n is O(n) with c=k=1.
When using logarithms inside big-Oh notation, the base does not matter. Recall the change-of-base formula: logbn=lognlogb. Therefore, as long as the base b is a constant, it differs from logn by a constant factor.
Here are some common functions, listed from slowest to fastest growth: O(1),O(logn),O(n),O(nlogn),O(n2),O(2n),O(n!) Caution: there are infinitely many functions between each element of this list!
Big-Omega Notation
As we saw above, big-Oh provides an upper bound for a function. To specify a lower bound, we use big-Omega notation.
Let f and g be functions from Z→R or R→R. We say f(x) is Ω(g(x)) if there are constants c>0 and k>0 such that 0≤c×g(n)≤f(n) for all x≥k. The constants c and k are called witnesses. We read f(x) is Ω(g(x)) as "f(x) is big-Oh of g(x)". We write f(x)∈Ω(g(x)) or f(x)=Ω(g(x)) (though the former is more technically correct).
Basically, f(x) is Ω(g(x)) means that, after a certain value of x, f is always bigger than some constant multiple of g:
Here are some examples that use big-Omega notation:
- To show that 5x3+3x2+2 is Ω(x3): 5x3+3x2+2≥5x3≥x3 Therefore, take c=k=1.
- To show that x2−3x+4 is Ω(x2): x2−3x+4=12x2+12x2−3x+4=12x2+(12x2−3x+4)≥12x2 The last step is true as long as 12x2−3x+4≥0, which is true when x>6. Therefore, take c=1/2,k=6.
-
Is it true that 3x+1 is Ω(x2)?
Suppose it is true. Then 3x+1≥cx2 for x>k. Dividing through by x2, we get that 3/x+1/x2≥c. Notice that as x gets bigger, the left hand side gets smaller, so this cannot be true. Therefore, 3x+1 is not Ω(x2).
- What is the sum of the first n integers? 1+2+3+⋯+n≥⌈n2⌉+(⌈n2⌉+1)+(⌈n2⌉+2)+⋯+n≥⌈n2⌉+⌈n2⌉+⋯+⌈n2⌉=(n−⌈n2⌉+1)⌈n2⌉≥(n2)(n2)=n24 Therefore, take c=1/4,k=1 to show that the sum is Ω(n2) (which matches with our formula for this sum).
Big-Theta Notation
In the previous example, we showed that ∑ni=1i=Ω(n2). Earlier, we also showed that this sum is O(n2). We have special notation for such situations:
Let f and g be functions from Z→R or R→R. We say f(x) is Θ(g(x)) if f(x) is O(g(x)) and f(x) is Ω(g(x)). We read f(x) is Θ(g(x)) as "f(x) is big-Theta of g(x)". We write f(x)∈Θ(g(x)) or f(x)=Θ(g(x)) (though the former is more technically correct).
It might be helpful to think of big-Oh/Omega/Theta as follows:
- ≤ is to numbers as big-Oh is to functions
- ≥ is to numbers as big-Omega is to functions
- = is to numbers as big-Theta is to functions