Home > CS3310: Design and Analysis of Algorithms > Algorithm Analysis FundamentalsAlgorithm Analysis Fundamentals
Time efficiency is analyzed by determining the number of repetitions of the basic operation as a function of input size (n).
Basic Operation: The operation that contributes most towards the running time of the algorithm.
\boxed{ \text{Running Time: } T ( n ) \approx c_{op} C(n) } \\ \small \textit{where $T$ is running time,} \\ \textit{$n$ is input size,} \\ \textit{$c$ is execution time for basic operation, and} \\ \textit{$C$ is \# of times basic operation is executed} \\
In short, we care about:
- How long the basic operation takes, and
- How many times we do it.
Problem | Input Size Measure | Basic Operation |
---|---|---|
Searching for key in a list of n items | # of list’s items (n) | Key comparison |
Multiplying two matrices | Matrix dimensions or total # of elements | Multiplication of two numbers |
Checking if a given integer n is prime | n’size = # of digits (in binary representation) | Division |
Typical graph problem | # of vertices and/or edges | Visiting a vertex or traversing an edge |
Remember: The size and format of input may impact the time efficiency of an algorithm.
Some algorithms’ efficiency depends on form of input.
\boxed{ \text{Worst Case: } C_{\text{worst}}(n) - \text{max over inputs of size $n$} } \\~\\ \boxed{ \text{Best Case: } C_{\text{best}}(n) - \text{min over inputs of size $n$} } \\~\\ \boxed{ \text{Average Case: } C_{\text{avg}}(n) - \text{avg over inputs of size $n$} }
Remember: The average case is NOT the average of the worst and best case!
Q: Find the worst and best case of this sequential search algorithm.
ALGORITHM SequentialSearch(A[0..n-1],k)
// Searches for given value in given array
// Input: Array (A) and search key (k)
// Output: Index of first element that matches K, or -1 if no matches
i \leftarrow 0
while i \lt n and A[i] \ne K do
i \leftarrow i \text{$+$} 1
if i \lt n return i
else return -1
A:
Q: Find the worst and best case of this sequential search algorithm.
ALGORITHM SequentialSearch(A[0..n-1],k)
// Searches for given value in given array
// Input: Array (A) and search key (k)
// Output: Index of first element that matches K, or -1 if no matches
i \leftarrow 0
while i \lt n and A[i] \ne K do
i \leftarrow i \text{$+$} 1
if i \lt n return i
else return -1
A:
In the case of a successful search, the probability of the first match occurring in the ith position of the list is p/n for every i,
In the case of an unsuccessful search, the number of comparisons will be n with the probability of such a search being (1-p)
Thus, the total expected comparisons is simply the addition of the above two expectations:
C_{\text{avg}}(n) = \textcolor{green}{ \left[ 1 \times \frac{p}{n} + 2 \times \frac{p}{n} + ... + i \times \frac{p}{n} + ... + n \times \frac{p}{n} \right] } + \textcolor{red}{ n (1-p) } \\~\\ \small\textit{Left term (green): Case 1; Right term (red): Case 2}
Now, we can simplify:
\begin{aligned} C_{\text{avg}}(n) &= [ 1 \times \frac{p}{n} + 2 \times \frac{p}{n} + ... + i \times \frac{p}{n} + ... + n \times \frac{p}{n} ] + n (1-p) \\ &= \frac{p}{n} [ 1 + 2 + ... + i + ... + n ] + n(1-p) \\ &= \frac{p}{n} \frac{n(n+1)}{2} + n(1-p) \\ &= \frac{p(n+1)}{2} + n(1-p) \end{aligned}
Therefore, the average case is:
C_\text{avg}(n) = \frac{p(n+1)}{2} + n(1-p)
Sometimes it’s better to analyze multiple runs rather than a single run.
Etymology: Amortization is from finance
- It’s about spreading the cost of the worst case over the life of the algorithm (useful for like compounding APR)
Asymptotic Analysis: Analysis of order of growth. Asymptotic: The nature of a graph/function as it reaches large values.Definition: Asymptotic
Order of Growth: The dominant behavior of an algorithm as n \to \infin.
n | log_2 n | n | n log_2 n | n^2 | n^3 | 2^n | n! |
---|---|---|---|---|---|---|---|
10^1 | 3.3 | 10^1 | 3.3 \times 10^1 | 10^2 | 10^3 | 10^3 | 3.6 \times 10^6 |
10^2 | 6.6 | 10^2 | 6.6 \times 10^2 | 10^4 | 10^6 | 1.3 \times 10^{30} | 9.3 \times 10^{157} |
10^3 | 10 | 10^3 | 1.0 \times 10^4 | 10^6 | 10^9 | ||
10^4 | 13 | 10^4 | 1.3 \times 10^5 | 10^8 | 10^{12} | ||
10^5 | 17 | 10^5 | 1.7 \times 10^6 | 10^{10} | 10^{15} | ||
10^6 | 20 | 10^6 | 2.0 \times 10^7 | 10^{12} | 10^{18} |
Why?: Looking at the asymptotic order of growth lets us compare functions by ignoring constant factors and small input sizes.
- e.g., Suppose you want to compare two array sorting algorithms. If all you analyze is how they perform on n = 5, any difference between them is negligible. It’s way more useful to see how each scales at very large n.