Complexity
https://slides.com/georgelee/ics141-algorithms-complexity/live
Big O
Not just for functions
Types of Complexity
Time Complexity
Analysis of how long an algorithm will take to complete.
Space Complexity
Analysis of how much memory (space) an algorithm will use in order to complete.
Both are Important
But we will only cover time
Time Complexity
Number of Operations
- Abstract away hardware specific features
- Formally, we look at number of "operations"
- Mostly just constants
- Worst case complexity
Complexity of Linear Search
def search(value, numbers):
"""
Linear search for a value in an array of numbers.
Returns the index of the value or -1 if it does not exist.
"""
for index, num in enumerate(numbers): # A comparison
if num == value: # A comparison
return index
return -1
Binary Search?
def binary_search(value, array):
"""Return the index of the value in the array, or -1 if it does not exist."""
start = 0
end = len(array) - 1
# How many times do we do this?
while start <= end: # A comparison
middle = int((start + end) / 2)
if array[middle] == value: # A comparison
return middle
elif value < array[middle]: # A comparison
end = middle - 1
else:
start = middle + 1
return -1
Binary Search Complexity
We divide the list in half each time. Assume that the number of items in the list is a power of two. That is,
n = 2k and k = log n.
How many items are in the list at each iteration?
Worst Case Complexity: O(log n)
Average Case Complexity
Worst case complexity is rather pessimistic. Sometimes we want to know on average how our algorithm performs.
Difficult to calculate for most algorithms.
Linear Search (Average)
How would we calculate the average case complexity for linear search?
We have the series:
2 + 4 + 6 + ... + 2n = 2(1 + 2 + 3 + ... + n) 2 (n ( n + 1 ) / 2 ) / n = n + 1 ϴ(n)
Sorting Algorithms
Bubble Sort Complexity
def bubble_sort(array):
# How many comparisons do we make?
for i in range(0, len(array) - 1):
for j in range(0, len(array) - i - 1):
if array[j] > array[j + 1]: # A comparison
array[j], array[j + 1] = array[j + 1], array[j]
return array
Insertion Sort Complexity
def insertion_sort(array):
# How many comparisons do we make?
for i in range(1, len(array)):
value = array[i]
position = i
for j in range(i, -1, -1):
if array[j - 1] <= value: # A comparison
break
array[j] = array[j - 1]
array[j] = value
return array
BogoSort
I have a sorting algorithm for you. How about we just generate ALL of the permutations of the array and then check if it's sorted?
What's the complexity of this algorithm?
Matrices
Matrix Multiplication
How many operations are performed when multiplying a a x b matrix by a b x c matrix?
The size of the matrix is a x c. Each time, we perform b multiplications and b - 1 additions.
Matrix Chain Multiplication
We know matrix multiplication is not commutative, but it is associative. Given matrices A1, A2, and A3, we want to find A1A2A3, but with the fewest number of operations.
Is A1(A2A3) or (A1A2)A3 better?
Algorithmic Paradigms
We covered one!
Greedy algorithms is an example
Brute Force Algorithm
When we "brute force" a problem, we try to solve it in the most straightforward way possible.
Many of the algorithms we covered are "brute force", in that we don't do anything special.
They are less efficient, but sometimes necessary.
Other Paradigms
- Dynamic programming
- Divide and conquer
Terminology
Complexity Terms
A constant time algorithm is O(1)
A logarithmic algorithm is O(log n)
A linear algorithm is O(n)
A linearithmic algorithm is O(n log n)
A polynomial algorithm is O(nb)
O(bn) is exponential
O(n!) is factorial
Tractability
Tractable Problems
Problems that can be solved in worst case polynomial time are tractable.
Exponential and factorial algorithms cannot be solved in a reasonable amount of time for large inputs. These are intractable problems.
P and NP
Tractable problems belong to a class of problems called P (polynomial time).
Intractable problems that can be verified in polynomial time belong to class NP (nondeterministic polynomial time).
NP Complete
For a problem to be NP-Complete, it must belong to NP and reduce down to an algorithm that is also NP-Complete.
How do you find the first NP-Complete algorithm? Take a grad-level course.
P vs. NP
Are problems that are NP actually in class P? If so, then that means any problem can be solved in polynomial time. This has huge implications for cryptography and solving intractable problems.
The current thought is P is not equal to NP, but there is no proof.
Complexity of Algorithms
By George Lee
Complexity of Algorithms
- 954