Recursion
Jessica Xu
Nov 18, 2024
CSCI 110 - Lecture 35
Today’s Agenda
|
|
| |
| |
| |
| |
Recap
sort()
sorted()
Both sort() & sorted()
Sorting students by name
students = [[‘Nirmal’, 39], [‘Michael’, 18], [‘Jeremy’, 19], [‘Constance’, 18], [‘Andre’, 19], [‘Deirdre’, 18], [‘Zade’, 19], [‘Conner’, 18]]
students.sort()
[[‘Andre’, 19], [‘Conner’, 18], [‘Constance’, 18], [‘Deirdre’, 18], [‘Jeremy’, 19], [‘Michael’, 18], [‘Nirmal’, 39], [‘Zade’, 19]]
Sorting students by age
students = [[‘Nirmal’, 39], [‘Michael’, 18], [‘Jeremy’, 19], [‘Constance’, 18], [‘Andre’, 19], [‘Deirdre’, 18], [‘Zade’, 19], [‘Conner’, 18]]
students.sort(key=lambda student : student[1])
[[‘Michael’, 18], [‘Constance’, 18], [‘Deirdre’, 18], [‘Conner’, 18], [‘Jeremy’, 19], [‘Andre’, 19], [‘Zade’, 19], [‘Nirmal’, 39]]
Using name as a secondary “tie breaker”
students = [[‘Nirmal’, 39], [‘Michael’, 18], [‘Jeremy’, 19], [‘Constance’, 18], [‘Andre’, 19], [‘Deirdre’, 18], [‘Zade’, 19], [‘Conner’, 18]]
students.sort(key=lambda student : (student[1], student[0]))
[[‘Conner’, 18], [‘Constance’, 18], [‘Deirdre’, 18], [‘Michael’, 18], [‘Andre’, 19], [‘Jeremy’, 19], [‘Zade’, 19], [‘Nirmal’, 39]]
Using name as a secondary “tie breaker” v2
students = [[‘Nirmal’, 39], [‘Michael’, 18], [‘Jeremy’, 19], [‘Constance’, 18], [‘Andre’, 19], [‘Deirdre’, 18], [‘Zade’, 19], [‘Conner’, 18]]
students.sort(key=lambda student : student[0])
[[‘Andre’, 19], [‘Conner’, 18], [‘Constance’, 18], [‘Deirdre’, 18], [‘Jeremy’, 19], [‘Michael’, 18], [‘Nirmal’, 39], [‘Zade’, 19]]
students.sort(key=lambda student : student[1])
[[‘Conner’, 18], [‘Constance’, 18], [‘Deirdre’, 18], [‘Michael’, 18], [‘Andre’, 19], [‘Jeremy’, 19], [‘Zade’, 19], [‘Nirmal’, 39]]
Sort by age (descending)
students = [[‘Nirmal’, 39], [‘Michael’, 18], [‘Jeremy’, 19], [‘Constance’, 18], [‘Andre’, 19], [‘Deirdre’, 18], [‘Zade’, 19], [‘Conner’, 18]]
students.sort(key=lambda student : (student[1], student[0]), reverse=True)
[[‘Nirmal’, 39], [‘Zade’, 19], [‘Jeremy’, 19], [‘Andre’, 19], [‘Michael’, 18], [‘Deirdre’, 18], [‘Constance’, 18], [‘Conner’, 18]]
Sorting Runtime
Different sorting algorithms also have different runtimes.
The default sort in every programming language has time complexity:
O(n log(n))
Recursion
Calling functions from other functions
def add_one(num):
return num + 1
def add_five(num):
for i in range(5):
num = add_one(num)
return num
print(add_five(10))
15
Calling functions from within that function
def add_one(num):
num = add_one(num) + 1
return num
print(add_one(10))
RecursionError: maximum recursion depth exceeded
Imagine you are waiting in a line…
Imagine you are waiting in a line…
How do you determine how long the line is?
You could just get out of line and count!
What if it is a really long line?
Imagine you are waiting in a line…
How do you determine how long the line is?
You could still count! But it might take awhile...
What if no one will save your spot in line? Getting out of line would make you have to go to the end :/
It is too far to see the entire line from where you are standing...
Idea!
Ask your neighbor! Maybe they know?
me
Hey do you know how long this line is?
Idea!
me
Nope but I can ask!
Idea!
me
Hey do you know how long this line is?
Idea!
me
Nope but I can ask!
Idea!
me
Hey do you know how long this line is?
Idea!
me
Nope but I can ask!
Idea!
me
Hey do you know how long this line is?
Idea!
me
Yes i’m actually first in line!
Idea!
me
I’m second in line!
Idea!
me
I’m third in line!
Idea!
me
I’m fourth in line!
Idea!
me
I guess I’m fifth!
Recursion
Recursion
How long is the line?
def line_length(person):
if (you are first in line):
return 1
else:
# ask neighbor what position they are in, wait for response, add 1
return line_length(neighbor) + 1
Base Case
Recursive Case
Factorial
Code Factorial (iteratively = using a loop)
Function: factorial()
Input: number n
Output: n!
Examples:
factorial(0) -> 1
factorial(1) -> 1
factorial(2) -> 2 * 1 = 2
factorial(3) -> 3 * 2 * 1 = 6
Code using a loop
def factorial_iterative(n):
if n < 0:
raise ValueError("n cannot be negative")
elif n == 0:
return 1
else:
result = 1
for i in range(1, n + 1):
result = result * i
return result
Code Factorial (using recursion)
Function: factorial()
Input: number n
Output: n!
Examples:
factorial(0) -> 1
factorial(1) -> 1
factorial(2) -> 2 * factorial(1) = 2
factorial(3) -> 3 * factorial(2) = 6
Code using recursion
def factorial(n):
if n < 0:
raise ValueError("n cannot be negative")
if n == 0 or n == 1:
return 1
else:
return n * factorial(n - 1)
Fibonacci
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
0
1
1
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
1
1
1,
2
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
1
2
1,
2,
3
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
2
3
1,
2,
3,
5
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
3
5
1,
2,
3,
5,
8
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
5
8
1,
2,
3,
5,
8,
13
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1,
+
8
13
1,
2,
3,
5,
8,
13,
21
Fibonacci Sequence
Special sequence of numbers where a number in the sequence is the sum of previous two numbers!
Start with 0 and 1:
0, 1, 1, 2, 3, 5, 8, 13, 21...
Code Fibonacci Sequence
Function: fibonacci()
Input: number n
Output: nth value in Fibonacci Sequence
Examples:
fibonacci(0) -> 0
fibonacci(1) -> 1
fibonacci(2) -> 1
fibonacci(3) -> 2
fibonacci(4) -> 3
fibonacci(5) -> 5
fibonacci(6) -> 8
fibonacci(7) -> 13
Code using a loop
def fibonacci(num):
if num <= 1:
return num
num_1 = 0
num_2 = 1
for i in range(num - 1):
temp = num_2
num_2 = num_2 + num_1
num_1 = temp
return num_2
Thinking recursively
Can I define this problem in terms of itself?
Hint: What if I start from the top (n) instead of from the bottom (0 & 1)?
fibonacci(4) -> 3
fibonacci(5) -> 5
fibonacci(6) -> 8
fibonacci(7) -> 13
fibonacci(0) -> 0
fibonacci(1) -> 1
fibonacci(2) -> 1
fibonacci(3) -> 2
Thinking recursively
f(5) = f(4) + f(3)
f(3) + f(2)
f(2) + f(1)
f(2) + f(1)
f(1) + f(0)
f(1) + f(0)
f(1) + f(0)
Thinking recursively
f(5) = f(4) + f(3)
f(3) + f(2)
f(2) + f(1)
f(2) + f(1)
f(1) + f(0)
f(1) + f(0)
f(1) + f(0)
Thinking recursively
f(5) = f(4) + f(3)
f(3) + f(2)
f(2) + 1
f(2) + 1
1 + 0
1 + 0
1 + 0
Thinking recursively
f(5) = f(4) + f(3)
f(3) + 1
1 + 1
1 + 1
Thinking recursively
f(5) = f(4) + 2
2 + 1
Thinking recursively
f(5) = 3 + 2
Thinking recursively
f(5) = 5
Code Fibonacci Sequence
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
Base Case
Recursive Case
Motivation
Why learn recursion?
Population count
def update_population_count(population):
world_population = 0
for continent in population:
continent_population = 0
for country in population[continent]:
country_population = 0
for state in population[continent][country]:
state_population = 0
for city in population[continent][country][state]:
state_population += population[continent][country][state][city]
population[continent][country][state]['total'] = state_population
country_population += state_population
population[continent][country]['total'] = country_population
continent_population += country_population
population[continent]['total'] = continent_population
world_population += continent_population
population['total'] = world_population
Population count
def update_population_count(population):
if type(population) != dict:
return population
else:
total = 0
for key in population:
total += update_population_count(population[key])
population['total'] = total
return total
Problems with complex structures
Recursion helps to solve problems that involve exploring all possible paths or combinations within a complex structure.
Ex. Finding all files in a directory and its subdirectories.
Use recursion to traverse the file system, exploring each directory and its subdirectories until you reach the "leaves" (files).
Questions?
Reminders
Reminder: Project 2 (pt. 3)
Reminder there are no late submissions for the projects!
Reminder: Project 2 (pt. 4)
Due next Monday @ 11:59pm!
Don’t forget the extra credit (practice problems) that is due on Wednesday November 27th @ 11:59pm!
Reminder: HW 11
Reminder: HW 12 – LAST ONE!
Retake: Quiz 9
Final Lab TOMORROW!
Final Exam
When: During your lab on Tuesday, December 3rd!
Where: TBD
Afterwards, there will be an Engineering Director from Google who has volunteered their time to give you a Tech Talk on Tuesday, December 3rd @ 4pm!
Grades!
Googler TAs and Career Coaches!
Need some extra support?
Book virtual OH with some folks from Google!
https://sites.google.com/corp/view/gir-career-coaches
Email my Googler TAs: