Lecture 6: Time Complexity Analysis of Program
Efficiency
How to determine complexity of
different code structures
It
depends on what kinds of statements are in the code
1
Sequence
of statements: s1; s2; s3; … sk;
Time
for whole seq =
sum of times for each statement
If
each stmt only involves a fixed number of basic ops,
Then each is O(1)
Total time is also O(1)
2
If
– then – else statements:
if (cond)
{
then {
Seq of stmts
1
}
else {
Seq of Stmts
2
}
executes either seq1 or seq 2
worst case time is:
max (time (seq1), time (seq 2)) + time (cond)
test yourself:
Time(cond) |
Time(seq1) |
Time(seq2) |
Total
Time |
O(1) |
O(1) |
O(1) |
O(1) |
O(1) |
O(N) |
O(1) |
O(N) |
O(1) |
O(N) |
O(N) |
O(N) |
O(N) |
O(N) |
O(1) |
O(N) |
O(N) |
O(N) |
O(N) |
O(N) |
O(1) |
O(N2) |
O(1) |
O(N2) |
if you finish early, check with your neighbor,
make some up for
your partner
3
Loops
For (k=0; k < N; k++) {
Seq
of stmts
}
loop executes N times; seq of stmts executes N times
total time = N ´ time for seq of statements:
time for stmts: O(1) O(N) O(M)
total time: O(N) O(N2) O(N´M)
4
Nested Loops
case #1: number of
iterations of inner loop is
independent
of outer loop index
for (j=0; j < N; j++) {
seq1 of stmts
for (k=0; k < M;
k++) {
Seq2 of stmts
}
}
· outer
loop executes N times
· each
time, inner loop executes M times
· seq of stmts executes N´M times
total
time = N
´ (time(seq1) + M ´
time(seq2))
time for stmts: O(1)
O(N) O(M) O(P)
total
time: O(N´M) O(N2M) O(NM2) O(NMP)
case #2: number of iterations of inner loop
depends
on outer loop index
for (j=0; j < N; j++) {
for (k=j; k < N;
k++) {
Seq
of stmts
}
}
· outer
loop executes N times
· inner
loop executes N, N-1, N-2, …, 2, 1
· seq of stmts executes N(N+1)/2 times
total
time = N
´ M ´ time for seq of statements:
time for stmts: O(1)
O(N) O(M)
total
time: O(N2) O(N3) O(N2M)
Statements with method calls:
example: Object k = L.get(1);
time: get is O(1), assignment is O(1), total is O(1)
·
time
for statement includes the time for the get method
·
time
for get may depend on value of parameter, fields
Read Announcements HERE
Handout: what is the complexity of each block of code?
Example
1
Object ob = L.get ( L.size() );
Example
2
Object ob = L.remove(0);
Example
3
for (int
k=0; k < L.size(); k++) {
System.out.println(L.get(k));
}
Example
4
for (int
k=L.size(); k>0; k--) {
L.remove(k));
}
Example
5
for (int
k=L.size(); k>0; k--) {
L.remove(1));
}
Solutions:
Example 1: O(1)
Examples 2,3,4: O(N)
Example 5: O(N2)
Summary:
· goal
is to determine how running time changes with the problem size, N
· time
~ number of operations
·
use "Big-O" notation
–
ignore constants & lower order terms
be
able to analyze code to find:
what is the
problem size?
what is the
worst case time?
how to
express it using Big-O notation
some
typical complexities:
O(1) constant time doesn't change when N doubles
O(N) linear time doubles " "
"
O(log N) logarithmic time goes up by 1 "
" "
O(N2) quadratic time quadruples
" "
"
O(N3) cubic
O(2N) exponential time doubles when N goes up by 1
Review of Java types (not needed?)
·
primitive types: int, double, char, …
· reference types: arrays, objects defined by classes
5 k
examples:
int k=5;
5 j
int j=k; // j has a copy of value of k
A
int [] A,B;
B
A =
new int[3];
B =
A; // B has copy value of A
B[1]
= 5; //changes A[1] also – called
"aliasing"
B =
null; //changes
B itself; doesn't change A
L
List
L; // contents of L = ??
L =
new List(); //items ¹
?? --why? look at constructor
L
aliasing
happens when ref. is passed as an argument in a method call; e.g., L.add(ob);
(discussed in lecture 2)
Review: Boolean expressions
In Java,
· boolean
expressions are evaluated left to right
· evaluation
stops when result is known
called
"Boolean short-circuiting"
example:
if (pos != k &&
get(k).equals(get(pos)))
if pos =
k, the second expression is not evaluated
thus,
· put
the less expensive expression first
similarly,
boolean result = false;
for
(k=0; k < numItems; k++){
if (pos != k
&& get(pos).equals(get(k)))
result =
true; // can return true here
}
return result;