Big O Practice
Jake Shoudy
Oct 7, 2022
CSCI 110 - Lecture 21
Announcements
HW7
Due tonight!
2D Lists and Image Filters
Image questions have public tests that are mostly useful (red_stripes test still is a little weird). Esp
Project 1: Part 5 (Optional)
Posted on Ed. Completely optional!
Extra credit available:
DUE before the end of October (show Jake at office hours)
UPDATED DUE DATE: Project 2: Part 1
Build a simple search engine using 1D lists :)
UPDATED DUE DATE: Friday October 14th, 11:59pm
Style Guide
Linked at the top of the class website :)
Reminder: FALL BREAK!
No class next Monday or Tuesday!
Recap
Lower-Order Terms
Name | Function | Examples |
constant | 1 | 1, 5, 10 |
logarithmic | log(n) | log(2n), 3log(n) |
linear | n | 4n, 0.5n, n |
log-linear | n log(n) | 3nlog(n), nlog(0.5n) |
polynomial | nc | 2n2, 5n3 |
exponential | cn | 2n, 5n + 1 |
Lower “order”
Higher “order”
More efficient
Less efficient
Simplification Examples
Drop lower order terms and multiplicative factors
Focus on dominant term: term that will increase the fastest
9999 + 0.1 * n
10n100 + 2n
log(n) + 10 * n * log(n) + 500n
101000
0.1n O(n)
2n O(2n)
10n log n O(n log n)
101000 * 1 O(1)
Example: create_countdown
def create_countdown(x):
result = []
for i in range(x):
result.insert(0, i)
return result
O(n)
O(1)
n * n + 1
= n^2 + 1
=> O(n^2)
O(n)
Example: create_countdown
def create_countdown(x):
result = []
for i in range(x-1, -1, -1):
result.append(i)
return result
O(n)
O(1)
n * 1 + 1
= n + 1
=> O(n)
O(1)
Space Complexity
Space Complexity
The same way we’ve been thinking about time complexity, we can analyze the space complexity of a particular solution.
Space Complexity refers to how much space in memory a program uses when it runs (including storing the parameter)
For time complexity, our unit was “operations”. For space complexity, we think about number of single “units” written to memory:
Space Complexity - Big O
We talk about space complexity in terms of Big O as well.
def mystery(n): num1 = n * 2 num2 = n + 6 return num1 + num2 |
Stores parameter n
Creates 2 new integers in memory
O(3) = O(1), so constant space complexity
Space Complexity - Big O
We talk about space complexity in terms of Big O as well.
def mystery1(nums, item): length = len(nums) new_list = [] for num in nums: if num == item: break new_list.append(num) return new_list |
In the worst case, creates a new list with n items in it (where n is the length of the given list `nums`), and 1 new integer variable in memory.
O(n + 1) = O(n), linear space complexity
Space Complexity - Big O
We talk about space complexity in terms of Big O as well.
def mystery2(nums): length = len(nums) new_list = [] for i in range(length): new_list.append([]) for j in range(length): new_list[i].append(nums[i] * nums[j]) return new_list |
Creates a new list with n lists inside of it. Each of those n lists contain n items (where n is the length of the given list `nums`)
O(n * n + n) = O(n^2), polynomial space complexity
Big O Practice
Example: remove_vowel_start
def remove_vowel_start(items, item):
if item in items and item[0] in 'aeiou':
items.remove(item)
return True
return False
O(n)
O(1)
Time Complexity:
O(n) + O(1) + O(n)
= O(n + 1 + n)
= O(2n + 1)
= O(n)
O(n)
Space complexity:
Input list of size n
No new variables
O(n)
Example: clean_list_v1
def clean_list_v1(my_list):
for num in my_list:
if 0 in my_list:
my_list.remove(0)
O(n)
Time Complexity:
O(n) * (O(n) + O(n))
= O(n * 2n)
= O(2n^2)
= O(n^2)
O(n)
Space complexity:
No new variables!
O(n)
O(n)
Example: clean_list_v2
def clean_list_v2(my_list):
while 0 in my_list:
my_list.remove(0)
O(n)
Time Complexity:
O(n) * O(n)
= O(n^2)
O(n)
Space complexity:
No new variables!
O(n)
Example: clean_list_v3
def clean_list_v3(my_list):
result = []
for num in my_list:
if num != 0:
result.append(num)
return result
O(n)
Time Complexity:
O(1) + O(n) * O(1)
= O(n)
Space complexity:
Created a new list up to
size n.
O(n) + O(n)
= O(2n)
= O(n)
O(1)
Example: repeat_letters
def repeat_letters(my_string):
for char in my_string:
for i in range(5):
print(char)
O(n)
O(1)
Time Complexity:
O(n) * (O(1) + O(1))
= O(n) * O(1)
= O(n)
O(1)
Space complexity:
No new variables!
O(n)
Example: rotate_colors
def rotate_colors(pixels):
pixels_copy = copy.deepcopy(pixels)
for row in len(pixels):
for col in len(pixels[row]):
for value in len(pixels[row][col]):
pixels_copy[row][col][value] = pixels[row][col][value + 1 % 3]
return pixels_copy
O(n)
O(1)
Time Complexity:
(where k is # of columns)
O(n*k) + O(n) * O(k) * O(1)
= O(n*k) + O(n*k)
= O(n*k)
O(k)
Space complexity:
Created a copy of the 2D list
O(n^2) + O(n^2)
= O(2n^2)
= O(n^2)
O(n*k)
O(1)
Example: binary_search
def binary_search(nums, target):
low = 0
high = len(nums) - 1
middle = 0
while low <= high:
mid = (high + low) // 2
if nums[mid] < target:
low = mid + 1
elif nums[mid] > target:
high = mid - 1
else:
return mid
return -1
O(1)
O(?)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 14
middle = 0
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 14
middle = 7
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 6
middle = 7
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 6
middle = 3
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 2
middle = 3
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 0
high = 2
middle = 1
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 2
high = 2
middle = 1
binary_search(my_list, 12)
Example: binary_search
5 | 10 | 12 | 13 | 28 | 45 | 67 | 80 | 82 | 85 | 87 | 87 | 92 | 98 | 99 |
low = 2
high = 2
middle = 2
binary_search(my_list, 12)
Example: binary_search
def binary_search(nums, target):
low = 0
high = len(nums) - 1
middle = 0
while low <= high:
mid = (high + low) // 2
if nums[mid] < target:
low = mid + 1
elif nums[mid] > target:
high = mid - 1
else:
return mid
return -1
O(1)
# of times I need to divide my list in half until I have just one element
Ex: 128 // 2 // 2 // 2 // 2 // 2 // 2 // 2� -> 7
2 ^ 7 = 128
2 ^ x = n
x = log(n)
O(log(n))
Questions?