### Overview of different "classes" of Computer Algorithms

• The "growth" of function

• Consider the following algorithms:

 ``` int N; int i; for ( i = 0; i < N; i++ ) do_fundamental_op(); ```

The do_fundamental_op() is executed N times

We say that:

 The running time increases linearly with the parameter N

• Now consider the following algorithms:

 ``` int N; int i, j; for ( i = 0; i < N; i++ ) for ( j = 0; j < N; j++ ) do_fundamental_op(); ```

The do_fundamental_op() is executed N2 times

We say that:

 The running time increases quadratically with the parameter N

• Clearly, the function N2 grows faster than the function N

• The O-notation

• Sometimes, we do not care to find the exact running time of an algorithm, but only how fast the running time grows with a certain parameter.

Examples: running times

 ``` Running time of algorithm 1 = N2 Running time of algorithm 2 = 4 N2 Running time of algorithm 3 = 100 N2 ```

All the above running times grows quadratically with the parameter N

• The growth of running times of algorithms are commonly expressed using the O-notation

• Definition:

A function g(N) is O(f(N)) (big-O f(N)) if there exist constants c0 and N0 such that:

 ``` g(N) < c0 f(N) for all N > N0 ```

Graphically:

• Example: g(N) = 4 N2 is O(N2)

 ``` Proof: Let c0 = 5 Let N0 = 0 Clearly: 4 N2 < 5 N2 for N > 0 or 4 N2 < c0 N2 for N > N0 ```

Hence: g(N) = 4 N2 is O(N2)

• Example: g(N) = 100 N2 is also O(N2)

Proof: same as above, just use c0 = 101

• Growth classes

• Different algorithms have different running times.

• The running times of the algorithms can be categorized into a number of classes

• Some common growth classes are:

 O(1) (constant running time) O(log(N)) (logarithmic running time) O(N) (linear running time) O(N log(N)) O(N2) (quadratic running time) O(N3) (cubic running time) O(2N) (exponential running time)

• Example constant running time algorithm

• An algorithm with constant running time always perform at most a constant number of operations

 ``` int numberGrade; // Assume it has been given a value if ( numberGrade >= 90 ) System.out.printf("A"); else if ( numberGrade >= 80 ) System.out.printf("B"); else if ( numberGrade >= 70 ) System.out.printf("C"); else if ( numberGrade >= 60 ) System.out.printf("D"); else System.out.printf("F"); ```

The algorithm will perform at most 4 comparisons (if-statements)

Because 4 is a constant, the running time of this algorithm is O(1)

• Example linear running time algorithm

• Example: find the max value in an array of N items

 ``` int N; int A[N]; // Assume it has been given values int i, max max = A[0]; for ( i = 0; i < N; i++ ) if ( A[i] > max ) max = A[i]; ```

• The algorithm will always perform N comparisons (if-statements), so:

 running time = N

Thus, the running time of this algorithm is O(N)

• What to aim for in running time analysis

• Fact:

 We are mainly interested in the running time for very large input sets

That is the case when "time" will matter...

But: we also aim for accuracy when it can be achieved with not too much effort

• So:

• When possible: find the exact running time

• When the expression gets "messy" (has too many terms): approximate (by ignoring the smaller terms)

Example:

 Running time = 5n2 + 23n + 4log(n) + 78 Aproximate by: 5n2

• When the expression is very complicated: simplify

In such a case, we will only find the order of the running time.

We will probably not be dealing with such complicated situations in this course...