Asymptotic Analysis Lec 1 | MIT 6.046J / 18.410J Introduction to Algorithms (SMA 5503), Fall 2005
- Pre-requisites
- 6.042 - Math and Computer Science
- 6.001 - Discrete Math, Probability, Programming
- Analysis of algorithms: Theoretical study of computer program performance and resource usage (communication, memory)
- What's more important than performance? Correctness, simplicity, maintainability, programmer time, stability, features (wide features than competitors), modularity (simple change requires small change), security, user-friendliness
- Why then study performance? correlated with user friendliness, real-time constraints, measures line between feasible and infeasible (it may not be functional), a language to talk about program behavior (global), performance can be used to pay to other things (security, user-friendliness, ...) (saves resources), speed is fun
- What's more important than performance? Correctness, simplicity, maintainability, programmer time, stability, features (wide features than competitors), modularity (simple change requires small change), security, user-friendliness
- Example:
- <a1, a2, ..., an> of numbers
- Output: permutation <a1',a2',...,an'> such that a1'<=a2'<=...<=an'
- Insertion Sort:
- Time complexity:
- If the array is already sorted - least work
- If the array is reverse sorted - most work
- Depends on array size
- Parameterize in input size (time as function of size)
- Want upper bounds (no more than certain amount) - guarentee for user
- Time complexity:
- Kinds of analysis
- Worst case analysis (usually)
- T(n) = max time on any input of size n (function and not a relation for max)
- Average case (sometimes)
- T(n) = expected time for all inputs of size n (probability of each input assumed)
- Assumption of a statistical distribution of inputs
- Equally likely (common assumption)
- Assumption of a statistical distribution of inputs
- T(n) = expected time for all inputs of size n (probability of each input assumed)
- Best case analysis (bogus) - we can cheat (slow algorithm that is fast on some input)
- Worst case analysis (usually)
- What times?
- Depends on computer
- Solution - relative speed (on same machine)
- Solution - absolute speed (algorithm that is better irrespective of time)
- Asymptotic analysis
- Ignores machine dependent constants
- Look at growth of running time (T(n)) as n -> infinity
- Depends on computer
- Notations:
- Theta notation: Drop low order terms and ignore leading constants
- Example: 3n^3 + 90n^2 + 6046 ~ Theta(n^3)
- Mathematical definition? Definition in terms of sets of functions
- As n -> Infinity, Theta(n^2) always beats Theat(n^3) algorithm in speed
- It satisfies both relative and absolute speed requirements
- Machine dependent constants get insignificant as n -> infinity
- As n -> Infinity, Theta(n^2) always beats Theat(n^3) algorithm in speed
- Engineering concerns: A slower algorithm may be better with reasonable size inputs than faster algorithm
- Mathematical definition? Definition in terms of sets of functions
- Example: 3n^3 + 90n^2 + 6046 ~ Theta(n^3)
- Theta notation: Drop low order terms and ignore leading constants
- Insertion sort analysis
- Worst case: When input is reverse sorted (Assumption: basic operation always takes constant amount of time)
- T(n) = sum_2_n(Theta * j) = Theta(n^2)
- For small n it is moderately fast but not at all for large n
- T(n) = sum_2_n(Theta * j) = Theta(n^2)
- Worst case: When input is reverse sorted (Assumption: basic operation always takes constant amount of time)
- Merge sort a[1...n]
- If n = 1, done
- Recursively sort A[1..[n/2]] and A[[n/2 + 1]..n]
- Merge the two
- subroutine: Compare elements between two lists and select the smaller one and put it in the array
- Theta(n) on n total elements
- T(n) = Theta(1) + 2*T([n/2]) + Theta(n)
- Reccurrence: 1. T(n) = Theta(1) if n = 1, 2(T(n/2)) + Theta(n) if n > 1 1. Recursion tree: T(n) = 2T(n/2) + cn = 2*2T(n/2^2) + 2cn + cn = ... = 2^kT(n/2^k) + 2^(k-1)cn + 2^(k-2)cn + ... + cn = 2^kp + 2^(k-1)cn + ... + cn ~ cnlog(n) + Theta(n) ~ Theta(nlog(n)) 1. Faster if > 30 elements
- Theta(n) on n total elements
- subroutine: Compare elements between two lists and select the smaller one and put it in the array
- Asymptotic analysis
- f(n) = O(g(n)) means there are constants c > 0 and no > 0 such that 0 <= f(n) <= cg(n) for all n >= no
- 2n^2 = O(n^3) -> 2n^2 belongs to set O(n^3)
- f(n) = O(g(n)) means there are constants c > 0 and no > 0 such that 0 <= f(n) <= cg(n) for all n >= no
- Macro convention
- A set in a formula represents an acronymous function in that set
- Ex: f(n) = n^3 + O(n^2) - means there is a fucntion h(n) = O(n^2) such that f(n) = n^3 + h(n)
- n^2 + O(n) = O(n^2) (= means "is" here) - asymmetric =
- Means for any f(n) belongs to O(n) there is an h(n) belongs to O(n^2) such that n^2 + f(n) = h(n) - = can be chained
- A set in a formula represents an acronymous function in that set
- Atleast time:
- Omega notations: Omega(g(n)) = {f(n): such that there exists constants c > 0 and no > 0 such that 0 <= g(n) <= c(f(n))
- sqrt(n) = Omega(log n) for sufficiently large n
- Omega notations: Omega(g(n)) = {f(n): such that there exists constants c > 0 and no > 0 such that 0 <= g(n) <= c(f(n))
-
Tells how well the algorithm scales
-
Example:
- 45n^3 + 20n^2 + 19 = 84 (n=1)
- 45n^3 + 20n^2 + 19 = 459 (n=2)
- 45n^3 + 20n^2 + 19 = 47,019 (n=10)
- 45n^3 = 45,000 (n=10) - 20n^2 + 19 has little effect and will have little influence as n increases
- O(n^3)
-
Notations:
- O(1) - same amount of time regardless of the size of the input
- O(n)
- O(n^2)
- O(log n)
-
Code example:
public class BigONotation { private int[] theArray; private int arraySize; private int itemsInArray = 0; static long startTime; static long entTime; public static void main(String[] args) { BigONotation testAlgo2 = new BigONotation(100000); testAlgo2.generateRandomArray(); BigONotation testAlgo3 = new BigONotation(200000); testAlgo3.generateRandomArray(); BigONotation testAlgo4 = new BigONotation(300000); testAlgo4.generateRandomArray(); } // O(1) public void addItemToArray(int newItem) { theArray[itemsInArray++] = newItem; // O(1) algorithm since array can find position in the same amount of time regardless of the size of the array } // O(n) - worst case takes time proprotional to n public void linearSearchForValue(int value) { boolean valueInArray = false; String indexWithValue = ""; startTime = System.currentTimeMillis(); for(int i = 0; i < arraySize; i++) { if (theArray[i] == value) { valueInArray = true; indexWithValue += i + " "; } } System.out.println("Value found: " + valueInArray); endTime = System.currentTimeMillis(); System.out.println("Linear search took " + (endTime = startTime)); } public BigONotation(int size) { arraySize = size; theArray = new int[size]; } public void generateRandomArray() { for (int i = 0; i < arraySize; i++) { theArray[i] = (int) (Math.random() * 1000) + 10; } itemsInArray = arraySize - 1; } }