Lecture 2 3 Analysis of Algorithm s2024
Lecture 2 3 Analysis of Algorithm s2024
Spring 2024
Analysis of Algorithms
Lecturer: Do Thuy Duong
Outline
Algorithm analysis
Time complexity
Experimental approach
Theoretical approach
Count primitive operations
2
Program performance
Program performance is the amount of computer memory/space and time
needed to run a program.
Memory/Space Complexity:
Amount of memory a program occupies
Usually measured in Bytes, KB or MB
Time Complexity:
Amount of time a program needs to run
Usually measured by the number of operations
3
Time complexity
Time complexity is the amount of computer time a program needs to run.
Why we care about time complexity?
Some computers require upper limits for program execution times.
Some programs require a real-time response.
Time is still a problem for us. If there are many solutions to a problem, we’ll
choose the fastest.
In some cases: Theoretically, we can solve the problem, but practically, we
can't; it just takes too long when the input size gets larger. E.g: RSA public-
key cryptosystems.
4
Measuring the Runtime
(Experimental approach)
Calculate the actual running time:
Write a program that implements the algorithm
Run the program with data sets of varying size.
Determine the actual running time using a system call to measure time
(e.g. System.currentTimeMillis() );
Problem?
5
Measuring the Runtime
(Experimental approach)
Disadvantages:
1. Need to implement the algorithm, which may be difficult
2. Results are not indicative of the running time on other input size, which is
not included in the experiment.
3. In order to compare two algorithms, the same hardware and software
environments must be used.
6
Measuring the Runtime
(Theoretical approach)
Solution: Asymptotic Analysis.
Evaluate the performance of an algorithm in terms of input size
Doesn’t measure the actual running time. Calculate how the time taken by
an algorithm increases with the input size.
7
Measuring the Runtime
(Theoretical approach)
Advantages:
Use high-level description of the algorithms (pseudo-code or diagrams),
instead of language dependent implementations.
Measure the runtime as a function of the input size, n. (So, we know what
happens when n gets larger)
Care for all possible inputs.
Measure the runtime independent of the hardware/software environment.
8
Measuring the Runtime
(Theoretical approach)
Pseudo-code: A description of an algorithm that is:
More structured than usual prose
Less formal than a programming language
Example:
Algorithm arrayMax(A, n):
Input: An array A storing n integers.
Output: The maximum element in A.
Max ← A[0]
for i← 1 to n -1 do
if Max < A[i] then Max ← A[i]
return Max
9
Measuring the Runtime
(Theoretical approach)
Control flow:
if … then … [else …]
while … do …
repeat … until …
for … do …
Method declaration
Algorithm name (param1, param2)
Input …
Output …
10
Measuring the Runtime
(Theoretical approach)
Method:
Calls: object method (args)
Returns: return value
Expressions:
← Assignment (like = in Java)
= Equality testing (like == in Java)
n2 Superscripts and other mathematical formatting allowed
11
Measuring the Runtime
(Theoretical approach)
Diagrams:
12
Theoretical approach
How to evaluate?
Inspect the pseudo-code/diagram and count the number of
primitive operations executed by the algorithm:
Make an addition, assignment = 1 operation
Calling a method or returning from a method = 1 operation.
Index in an array = 1 operation.
Comparison = 1 operation, etc.
T(n): a function of the input size n
Primitive operations:
Basic computations performed by an algorithm
Largely independent from the programming language
Assumed to take a constant amount of time in the RAM model
13
Count primitive operations
Inspect the pseudocode
count the maximum
number of primitive
operations executed by
the algorithm as a
function of the input size
T(n)
T(n) = 6n-1.
14
Count primitive operations
• T(n) depends on the input data
• If A[0] is the maximum, then
the code Max A[i] will never
be executed (Best case):
T(n)=4n+1 (operations)
• If A[n-1] is the maximum, then
the code Max A[i] will always
be executed (Worst case):
T(n)=6n-1 (operations)
15
Best case Time complexity
The best case of an algorithm A is a function:
TBA: ℕ → ℕ where TBA(n) is the minimum number of steps performed by
A on an input of size n.
16
Worst case Time Complexity
The worst case of an algorithm A is a function:
TWA: ℕ → ℕ where TWA(n) is the maximum number of steps performed by A
on an input of size n.
17
Average case time Complexity
18
Worst case Time Complexity
19
Reasons for Worst-Case Analysis
Expect the best. Prepare for the worst know in advance what happen
when the input size gets huge (Programmers need to care when design
algorithms).
• Many algorithms perform to their worst case a large part of the time.
• The best case is not very informative because many algorithms perform
exactly the same in the best case hard to compare their performance.
• Determining average-case performance is not always easy.
• The worst case gives us an upper bound on performance.
Use worst-case running time as the main measure of time complexity
20
Count primitive operations
More examples
public int powerTwo (int n)
{
int result = n * n;
return result;
}
21
Count primitive operations
More examples
public int powerTwo (int n)
{
int result = n * n;
return result;
}
T(n) = 3
22
Count primitive operations
More examples
public int search (int n, int array[])
{
for (int i = 0, i<n, i++)
if (array[i] == 0)
return 0;
return 1;
}
23
Count primitive operations
More examples
public int search (int n, int array[])
{
for (int i = 0, i<n, i++)
if (array[i] == 0)
return 0;
return 1;
}
T(n) = 1+(n+1)+3n+n+1 = 5n+3.
24
Count primitive operations
More examples
25
Count primitive operations
More examples
27
Count primitive operations
Consider T(n):
• Too complicated
• Too many terms
• Difficult to compare two expressions, each with 10 or 20
terms
Do we really need that many terms?
28
Asymptotic behavior
Consider: T(n)= n3 + 10n2+20n+500
Note:
• When n=1,000
T(n)=1,000,000,000 + 10,000,000+20,000+500
• The value (behavior) of T(n) when n gets large is determined entirely by the
leading term (n3)
• We may drop all except the n3 term
The leading term (fastest growing term) will dominate the running time
29
Asymptotic behavior
To compare the time complexity of two algorithm
we compare the growing rate of the leading
terms. (Note: compare n3 and 2n when n = 1, 2, 4, 8,…)
30
Asymptotic behavior
To compare
the time complexity
of algorithms, we
compare the growing rate
of the leading terms.
31
We only need to know the leading term of the T(n) to evaluate time
complexity of an algorithm.
Calculate Big – Oh of the algorithm?
32
Big-Oh Notation
Big-Oh represents the worst case time complexity of an algorithm.
33
Big-Oh Notation
The Big-Oh notation definition:
• Let f, g: ℕ → R be functions.
f(n) is O(g(n)) if there is an n0 ∈ N
and a c > 0 in R such that
ꓯn ≥ n0 we have f(n) ≤ c*g(n).
Example:
f(n)=5n+3 ≤ 6*n ꓯn ≥ 3
f(n) ≤ 6*n ꓯn ≥ 3
g(n) = n f(n) is O(n).
34
The Big-Oh notation definition:
• Let f, g: ℕ → R be functions.
f(n) is O(g(n)) if there is an n0 ∈ N
and a c > 0 in R such that
ꓯn ≥ n0 we have f(n) ≤ c*g(n).
Example:
f(n)=7n+1 ≤ 8*n ꓯn ≥ 1
f(n) ≤ 8*n ꓯn ≥ 1
g(n) = n f(n) is O(n).
35
Big-Oh notation
Big-Oh represents an upper-bound of the growth rate of a function.
• If an algorithm needs T(n) = 5n+3 basic operations and another needs
T(n) = 7n+1 basic operations, we will consider them to be in the same
efficiency category. (they have the same Big-Oh notation O(n))
36
Big-Oh Notation
Example:
f(n)=3 ≤ 4*1 ꓯn ≥ 0
f(n) ≤ 4*1 ꓯn ≥ 0
g(n) = 1 f(n) is O(1).
37
Big-Oh Notation
Big-Oh notation proof:
Let f(n) = K (K is a constant), prove that f(n) is O(1)
(which means g(n) = 1)
Solution: We must find n0 and c such that for all n ≥ n0, we have
f(n) ≤ c*g(n)
Choose c = K+1 and n0 = 1
for all n ≥ 1 : f(n) = K<(K+1)* (1) g(n) = 1 f(n) = O(1).
38
Big-Oh Notation
Big-Oh notation proof:
Let f(n) = 2n2 + K (K is a constant), prove that f(n) is O(n2)
(which means g(n) = n2)
Solution: We must find n0 and c such that for all n ≥ n0, we have f(n) ≤
c*g(n)
Prove: 2n2 + K ≤ c*n2 = (c-1)*n2 + n2
We choose c = 3 and n0 ≥ 2n2 +( ≤ (3-1)*n2 + n2 f(n) is O(g(n)) =
O(n2)
39
Big-Oh notation
More Big-Oh notation example:
40
Assume the computer does 1 billion ops per second.
41
Estimate Big-Oh of an algorithm
• Method 1
Analyze the algorithm, estimate the total number of primitive
operations T(n).
Find T(n) is O(g(n)).
Method 2
Analyze the algorithm, estimate the Big-Oh for
each blocks
42
Method 1
43
Rules for calculating Big-Oh
44
Rules for calculating Big-Oh
45
Rules for calculating Big-Oh
Rule for sums:
O(f(n)) + O(g(n)) is O(max(f(n), g(n)))
Rule for products
O(f(n)).O(g(n)) is O(f(n).g(n))
The running time of each assignment, read, write statement can be taken to
be O(1)
The running time of a sequence of statements is determined by the sum rule
The running time of an if-statement is the cost of the conditionally executed
statements, plus the time for evaluating the condition..
The time to execute a loop is the sum, over all times around the loop.
46
Method 2 – General rules
47
Method 2 – General rules
Conditional block
Loop block
48
Method 2 – General rules
Nested loop:
Function call:
49
Example 1
50
Example 2
51
Example 3
52
Recurrence relation
Consider the recursive method factorial:
53
Recurrence relation
The runtime of the program
54
Recurrence relation
public void Test (int n)
{
if (n>0)
{
for (int i=0; i<n;i++)
System.out.println(i);
}
Test(n-1);
}
55
Recurrence relation
Method 2: Recurrence Tree Method
Method 3: Master Theorem Method
56
Tutorial and next topic
Preparing for the tutorial:
• Practice with examples and exercises in Tutorial 2
• Read textbook section 1.3 (Recursion), reference book chapter 3
57