Skip to content

Algorithms Complexity: All You Should Know About It

Published: at 09:22 PM

Introduction

Algorithm complexity is a measure of how long it would take an algorithm to complete given an input of size nn. If an algorithm has to scale, it should complete the result within a finite and practical time bound even for large values of nn. For this reason, complexity calculated asymptotically as nn approaches infinity.

In this article we are going to take a look at

Table of contents

Open Table of contents

Asymptotic Notations

Calculation number of operations allows you to compare the efficiency of algorithms. As we’ve mentioned in the Introduction section, the analysis is carried out with the expectation of a sufficiently large amount of processed data where nn \rightarrow \infin, therefore, the growth rate is a key of importance, not the exact number of operations.

At this moment, we are ready to deep dive into details. Let’s define the function classes and consider asymptotic notations that describe the running time for a particular program or algorithm:

For a given function g(n)g(n) the notation Θ(g(n))\Theta(g(n)) denotes: Θ(g(n))={f(n): c1 0  c2  0  n0 0  0c1g(n)f(n)c2g(n),nn0}\Theta(g(n)) = \{ f(n): \exist \space c_1 \ge \space 0 \space \exists \space c_2 \space \ge \space 0 \space \exist \space n_0 \space \ge 0 \space | \space 0 \le c_1g(n) \le f(n) c_2g(n), \forall n \ge n_0 \}

For a given function g(n)g(n) the notation O(g(n))O(g(n)) denotes: O(g(n))={f(n): c0  0f(n)cg(n),nn0}O(g(n)) = \{ f(n): \exist \space c \ge 0 \space | \space 0 \le f(n) \le cg(n), \forall n \ge n_0 \}

For a given function g(n)g(n) the notation Ω(g(n))\Omega(g(n)) denotes: Ω(g(n))={f(n): c0  0cg(n)f(n),nn0}\Omega(g(n)) = \{f(n): \exist \space c \ge 0 \space | \space 0 \le cg(n) \le f(n), \forall n \ge n_0\}

Image description


Comparing Functions

When we deal with complex algorithms, we are able to consider the limit of the ratio of the functions complexity:

limnfngnlim_{n \rightarrow \infin} \frac{f_n}{g_n}

Based on the limit result, we can calculate the growth rate of the function:

Also, we can consider a ratio of the derivatives of the function, like this:

limnfngn=fngnlim_{n \rightarrow \infin}\frac{f_n}{g_n}=\frac{f_n'}{g_n'}

if functions have the following properties:

Example

Compare two functions f(n)=nlog2nf(n)=n\log_2{n} and g(n)=log2n2019g(n)=\log_2{n}^{2019}

Proof:

limnf(n)g(n)=limn(nlog2n)(log2n2019) =limnlog2+12019log22018nn =limnnlog2n+12019log22018n= nlog2n=Ω(log2n2019)lim_{n \rightarrow \infin}\frac{f(n)}{g(n)}=lim_{n \rightarrow \infin}\frac{(n\log_2{n})'}{(\log_2{n^{2019}})'} \\\ =lim_{n \rightarrow \infin}\frac{log_2+1}{\frac{2019\log_{2}^{2018}n}{n}} \\\ =lim_{n \rightarrow \infin}\frac{n\log_2n+1}{2019*\log_{2}^{2018}n}=\infin \\\ \Rightarrow n\log_2{n} = \Omega(log_2{n^{2019}})


Master Theorem

Defenition

Let us have a recurrence relation of the following form:

T(n)={aT(nb)+O(nc),n > 1 O(1)n = 1\begin{equation} T(n) = \begin{cases} a*T(\frac{n}{b})+O(n^c), &\text{n > 1} \\\ O(1) &\text{n = 1} \end{cases} \end{equation}

where aN,bR,b>1,cR+a \in \mathbb{N}, b \in \mathbb{R}, b > 1, c \in \mathbb{R}^{+}. Then the solution of the given recurrence relation has the form:

Proof:

Let’s consider the recursion tree. It has logbn\log_bn levels where each kk-level has aka^k vertexes each of them costs (nbk)c(\frac{n}{b^k})^c.

Let’s summarize the cost of the tree at all levels:

T(n)=k=0logbnak(nbk)c=nck=0logbn(abc)kT(n)=\sum_{k=0}^{log_bn}a^k* \big( \frac{n}{b^k} \big)^c=n^c \sum_{k=0}^{log_bn} \big( \frac{a}{b^c} \big)^k

We get the tree cases:

  1. If c>logbac > \log_ba, then (abc)k\sum(\frac{a}{b^c})^k is the sum of a decreasing geometric progression (where abc<1\frac{a}{b^c} < 1), which doesn’t depend on nn. It means that the sum is just a constant. T(n)=Θ(n)T(n)=\Theta(n)
  2. If c=logbac = \log_ba, then T(n)=nck=0logbn(abc)k=nck=0logbn1k=Θ(nclogbn)T(n)=n^c\sum_{k=0}^{log_bn}(\frac{a}{b^c})^k=n^c\sum_{k=0}^{log_bn}1^k=\Theta(n^c\log_bn)
  3. If c<logbac < \log_ba, then since the sum of a progression is asymptotically equivalent to its leading element, we have the following: T(n)=nck=0logbn(abc)k=Θ(nc(abc)logbn)=Θ(ncalogbnnc)=Θ(alogbn)=Θ(nlogba)T(n)=n^c\sum_{k=0}^{\log_bn}(\frac{a}{b^c})^k=\Theta(n^c(\frac{a}{b^c})^{\log_{b}{n}})=\Theta(n^c*\frac{a^{\log_{b}{n}}}{n^c})=\Theta(a^{\log_{b}{n}})=\Theta(n^{\log_{b}{a}})

Recurrence Relations

There are three main methods for solving recurrence relations: substitution method, recursion tree and master theorem. Let’s consider them.

Substitution method

In order to solve a recurrence relation using the substitution method it’s necessary to complete two steps:

Example

Show that the solution of T(n)=T(n2)+1T(n)=T(\lceil \frac{n}{2} \rceil)+1 is O(lgn)O(\lg n)

Proof:

Assume that T(n)clg(na)T(n) \le c*\lg{(n-a)} (we used a definition of big-OO from the Asymptotic Notations part), where aa is a number which will be selected later. Now, we are ready to substitute it into initial recurrence.

Then,

T(n)clg(n2)a+1 clg(n+12a)+1clg2 clg(n+12a) clg(na)T(n) \le c* \lg{(\lceil \frac{n}{2})\rceil - a} + 1 \le \\\ c*\lg{(n+1-2a)}+1-c*\lg{2} \le \\\ c*\lg{(n+1-2a)} \le \\\ c*\lg{(n-a)}

We proved that O(lgn)O(\lg{n}) is a solution for the given relation when a1, c1a \ge 1, \space c \ge 1.


Let’s see another example.

Show that the solution of T(n)=T(n1)+nT(n)=T(n-1)+n is O(n2)O(n^2)

Proof:

Assume, that T(n)cn2T(n) \le c*n^2. Let’s substitute this inequality to a given recurrence.

Then,

T(n)c(n1)2+n=cn22cn+c+n= cn2+n(12c)+c cn2T(n) \le c*(n-1)^2+n =cn^2-2cn+c+n= \\\ cn^2+n(1-2c)+c \le \\\ cn^2

The last step completes when c12c \ge \frac{1}{2}.


Recursion Tree

Another way to find a solution for relation recursion is using a Recursion Tree.

In this method, a recurrence relation is converted into recursive tree. Each node represents the cost incurred at various levels of recursion. To find the total cost, cost of all levels are summed up.

Example

Use a recursion tree to determine a good asymptotic upper bound on the recurrence T(n)=4T(n2+2)+n)T(n)=4T(\frac{n}{2} + 2)+n). Use the substitution method to verify your answer.

Proof:

Image description

The tree has log2n\log_2{n} levels. The subproblem size for a node at depth ii is n2i\frac{n}{2^i}. The subproblem’s size reach 11 when n2i=1i=log2n\frac{n}{2^i}=1 \Rightarrow i=\log_2{n}.

The last level of depth log2n\log_2{n} contains 4log2n=n24^{\log_2{n}}=n^2.

The total cost over all nodes:

i=0logn1(4in2+2))+Θ(n2)= i=0logn1(2in+4i2)+Θ(n2)= i=0logn12in+i=0logn14i2+Θ(n2)= 2logn121n+24logn41+Θ(n2)= (2logn1)n+23(4logn1)+Θ(n2)= (n1)n+23(n21)+Θ(n2)=Θ(n2)\sum_{i=0}^{\log{n-1}}(4^i*\frac{n}{2}+2)) + \Theta(n^2)= \\\ \sum_{i=0}^{\log{n-1}}(2^in+4^i*2) + \Theta(n^2) = \\\ \sum_{i=0}^{\log_{n-1}}2^in+\sum_{i=0}^{\log{n-1}}4^i*2+\Theta(n^2)= \\\ \frac{2^{\log{n}}-1}{2-1}n+\frac{2*4^{\log{n}}}{4-1}+\Theta(n^2)= \\\ (2^{\log{n}}-1)n+\frac{2}{3}(4^{\log{n}}-1)+\Theta(n^2) = \\\ (n-1)n+\frac{2}{3}(n^2-1)+\Theta(n^2)=\Theta(n^2)

Verifying by using substitution method:

Assume that T(n)c(n2dn)T(n) \leq c(n^2-dn). Let’s substitute this inequality to a given recurrence.

Then,

T(n)4c((n2+2)2)d(n2+2)+n= 4c(n22+2n+4dn22d)+n= cn2+8cn+16c2dnc8dc+n= cn2cdn+8cn+16ccdn8cd+n= c(n2dn)(cd8c1)n+(d2)8c c(n2dn)T(n) \leq4c((\frac{n}{2}+2)^2)-d(\frac{n}{2}+2)+n = \\\ 4c(\frac{n^2}{2}+2n+4-\frac{dn}{2}-2d)+n= \\\ cn^2+8cn+16c-2dnc-8dc+n= \\\ cn^2-cdn+8cn+16c-cdn-8cd+n= \\\ c(n^2-dn)-(cd-8c-1)n+(d-2)8c \leq \\\ c(n^2-dn)

The last step completes when cd8c10cd-8c-1 \ge 0.


Master Theorem

Use the master theorem to give tight asymptotic bounds for the following recurrences:

a. T(n)=2T(n4)+1T(n)=2T(\frac{n}{4})+1 b. T(n)=2T(n4)+nT(n)=2T(\frac{n}{4})+\sqrt{n} c. T(n)=2T(n4)+nT(n)=2T(\frac{n}{4})+n

Proof:

a. a=2,b=4,c=1a=2, b=4, c=1. Hence, T(n)=Θ(n)T(n)=\Theta(\sqrt{n})

b. a=2,b=4,c=12a=2,b=4,c=\frac{1}{2}. Hence, T(n)=Θ(nlog4n)T(n)=\Theta(\sqrt{n}\log_4{n})

c. a=2,b=4,c=1a=2,b=4,c=1. Hence, T(n)=Θ(n)T(n)=\Theta(n)

Thanks for reading

If you enjoyed this post, be sure to follow me on Twitter to keep up with the new content.


avatar

Nikita Vasilev

A software engineer with over 7 years of experience in the industry. Writes this blog and builds open source frameworks.


Previous Post
Memory Management With Swift