0% found this document useful (0 votes)
0 views74 pages

Intro Python Part3

The document explains recursion, particularly in the context of calculating factorials and the Fibonacci series. It details the structure of recursive functions, including base cases and recursive calls, and provides examples of recursive algorithms in Python. Additionally, it discusses the advantages of recursion and provides an example of recursively summing elements in a list of lists.

Uploaded by

peachypaimon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views74 pages

Intro Python Part3

The document explains recursion, particularly in the context of calculating factorials and the Fibonacci series. It details the structure of recursive functions, including base cases and recursive calls, and provides examples of recursive algorithms in Python. Additionally, it discusses the advantages of recursion and provides an example of recursively summing elements in a list of lists.

Uploaded by

peachypaimon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 74

Recursion

1
Function calls
What happens when a function calls another functions ?
When a function terminates, its call A new function call opens a new
frame is removed from the stack frame to store local variables

h() s “h “

g() s “g “
f start
g start
f() s “f “
h start
h done
g done
Call Stack
f done
(LIFO) 2
Calculating Factorial
• n! = 1*2*3*…(n-1)*n
• An iterative implementation:

• An alternative Recursive definition:


• n! = n * (n-1)!
• 0! = 1
• Can we use this approach to implement another version of
factorial calculation in Python ?
3
Iterative Versus Recursive
Step by step (iteratively):
n! = 1*2*3*….*n 4! = 1*2*3*4 = 2*3*4 = 6*4 = 24
n iterations

Recursively:

n! = n*(n-1)! 4! = 4*3!
0! = 1 = 4*(3*2!)
= 4*(3*(2*1!))
=4*(3*(2*(1*0!)))
=4*(3*(2*(1*1)))
=4*(3*(2*1))
= 4*(3*2) = 4*6 = 24
4
Recursive Definition
Factorial

Calculate result using a recursive call

n! = n * (n-1)!
0! = 1
Smaller instance
Base condition

5
Recursive Implementation of
Factorial in Python

def factorial(n): stop condition

if n == 0:
return 1
return n * factorial(n-1)

calculate the result advance towards base case


using a recursive call

6
Recursion
Recursive function:
A function whose implementation calls itself (with different
arguments).

Recursive Solution
A solution to a “large” problem using solutions to “small”
problems that assemble it.

7
Recursive factorial – step by step

factorial(
4)n
4

Returns…

8
Recursive factorial – step by step

factorial(
4)n
4

Returns…

9
Recursive factorial – step by step

factorial(
4)n
4

Returns…
4*…

10
Recursive factorial – step by step

factorial(
factorial(
4)n
3)n
4
3
Returns…
Returns…
4*…

11
Recursive factorial – step by step

factorial(
factorial(
4)n
3)n
4
3
Returns…
Returns…
4*…

12
Recursive factorial – step by step

factorial(
factorial(
4)n
3)n
4
3
Returns…
Returns…
4*…
3*…

13
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n
2)n
4
3
2
Returns…
Returns…
4*… Returns…
3*…

14
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n
2)n
4
3
2
Returns…
Returns…
4*… Returns…
3*…

15
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n
2)n
4
3
2
Returns…
Returns…
4*… Returns…
3*…
2*…

16
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n
4 1)n
3
2
Returns… 1
Returns…
4*… Returns…
3*… Returns…
2*…

17
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n
4 1)n
3
2
Returns… 1
Returns…
4*… Returns…
3*… Returns…
2*…

18
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n
4 1)n
3
2
Returns… 1
Returns…
4*… Returns…
3*… Returns…
2*…
1*…

19
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n
4 1)n
3
2
Returns… 1
Returns…
4*… Returns…
3*… Returns…
2*…
1*…

20
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n factorial(
4 1)n
3 0)n
2
Returns… 1
Returns… 0
4*… Returns…
3*… Returns…
2*… Returns…
1*…

21
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n factorial(
4 1)n
3 0)n
2
Returns… 1
Returns… 0
4*… Returns…
3*… Returns…
2*… Returns…
1*…
1

22
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n factorial(
2)n
4 1)n
3
2
Returns… 1
Returns…
4*… Returns…
3*… Returns…
2*…
1*1

23
Recursive factorial – step by step

factorial(
factorial(
4)n factorial(
3)n
2)n
4
3
2
Returns…
Returns…
4*… Returns…
3*…
2*1

24
Recursive factorial – step by step

factorial(
factorial(
4)n
3)n
4
3
Returns…
Returns…
4*…
3*2

25
Recursive factorial – step by step

factorial(
4)n
4

Returns…
4*6

26
Recursion
 In every recursive call the problem is reduced.

 When the problem is small enough - solve


directly (base case).

A divide and conquer


strategy

27
General Form of Recursive Algorithms

Recursive case - decomposable problem.


Must be:
- at least one base case (the stop condition)
- at least one recursive call.

28
Short Summary
Design a recursive algorithm by
1. Breaking of big problems to smaller problems
2. Solving base cases directly.

Recursive algorithms have


1. Stopping criteria
2. Recursive call(s)
3. A solution that uses solutions of smaller cases

29
Example: Fibonacci Series
• Fibonacci series
0, 1, 1, 2, 3, 5, 8, 13, 21, 34
• Definition:
• fib(0) = 0
• fib(1) = 1
• fib(n) = fib(n-1) + fib(n-2)

30
Fibonacci
“Naturally” recursive

Therefore, the recursive definition is:


• fib(0) = 0 Base case

• fib(1) = 1 Base case

• fib(n) = fib(n-1) + fib(n-2) +


Recursive call

31
Example: Modulo

Given the following iterative version of modulo


calculation - find the recursive definition

1. Base case?
2. What is the recursive call?
3. How do we use the result of the recursive call to
calculate the value for n?

32
Solution: Recursive Modulo

33
Recursive List sum
• Given a list of numbers, calculate their sum using a recursive
function.

13
13

• Now write an alternative implantation that does not use slicing..

34
Recursive List sum

13
13
13
35
Additional examples
• Calculating the sum of sub-lists
• Using slicing
• Using indices (more efficient)
• Odd-Even

36
Recursive Sub-lists Sum
• Input: a list of lists, each internal list contains only
numbers
• Output: a list that contains the sums of each internal
list from the input.

• For example:
• For [ [1,2,3], [4] ] the result is [6, 4]

37
Recursive Sub-lists Sum
• More examples:
In this call, the input contains only one list.
The list has no elements, so its sum is 0.

In this call, there are no lists to sum, so


the output would be en empty list

The number of elements in the


returned list equals to the
number of lists in the input list
38
Recursive Sub-lists Sum
• The recursive implementation has 3 steps:
• Stop condition
• Advance toward the base case
• Solve the problem using a recursive call
Recursive Sub-lists Sum– base case

Easy!
Advancing towards the base condition
• The input is a list
• The base condition is an empty list
• A recursive call with a shorter list is considered to
be an easier case.
• Usually take off the first or last element
• In addition, we advance toward the base list: if we
take elements off the list, eventually we’ll get an
empty list.
Using the recursive call
Having an actual example may help
let’s consider this example [[1,2,3], [5],[6,1]]
input result
Our problem [[1,2,3], [5],[6,1]] [6, 5, 7]
Recursive call [[1,2,3], [5]] [6, 5]

How can we use the result of the recursive call?


If we got [6, 5], we need to append 7 to the list.
How do we get the item 7?
It’s the sum of the list [6,1]
Using the recursive call
input result
Our problem [[1,2,3], [5],[6,1]] [6, 5, 7]
Recursive call [[1,2,3], [5]] [6, 5]

• Our plan:
• Given a list:
• Put aside the last element
• Recursive call with a shorter list and save the
result
• Add to this result the sum of the last element we
put aside.
• Return the result.
And now in Python

recursive_res contains the result


of the recursive call

sum up the elements of the list


we put aside

Shorted version
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = []
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = []
recursive_res = ?
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = []
recursive_res = ?
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = []
recursive_res = ?
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = []
recursive_res = ? recursive_res = ?
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]] lst = []


[]
res = [] res = [] Stop condition!
recursive_res = ? recursive_res = ?
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = []
recursive_res = ? recursive_res = []
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = []
recursive_res = ? recursive_res = []
last_sum = 6
sum([1,2,3])
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = [] Copy all elements from
recursive_res to res
recursive_res = ? recursive_res = []
last_sum = 6
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] res = [6]
recursive_res = ? recursive_res = []
last_sum = 6
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]] lst = [[1,2,3]]


res = [] [6] res = [6]
recursive_res = ? recursive_res = []
last_sum = 6
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = []
recursive_res = [6]
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = []
recursive_res = [6]
last_sum = 9
sum([4,5])
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = [6] Copy all elements from
recursive_res to res
recursive_res = [6]
last_sum = 9
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = [6, 9]
recursive_res = [6]
last_sum = 9
Execution example for [[1,2,3], [4,5]]

lst = [[1,2,3], [4,5]]


res = [6, 9] As expected, the returned value
recursive_res = [6] is [6,9]
last_sum = 9
Alternative solution for recursively calculating the sum of
sub-lists:

WORKING WITH INDICES INSTEAD


OF SLICING STRINGS

62
Is the solution for Recursive Sum the
?most efficient

• In each recursive step we use slicing, which creates a


new (shorter) list
• Can we avoid slicing?
Recursive Sum – alternative solution
• We can use the same list for all the recursive calls.
• But how do we generate an “easier” problem?
• Add another parameter – the index of the current item
Recursive Sum – alternative solution
• Our plan:
• Given a list(lst) + the index of the current item (i):
• Put aside the last element lst[i]
• Recursive call with the shorter list the same list
and the index i-1 and save the result
• Add to this result the sum of the last element we
put aside.
• Return the result.
Recursive Sum – alternative solution
• The stop condition:
• Previously: stop when len(lst) == 0
• Now:
• What about i==0?
Not good! When i == 0 we still have one element to
consider: lst[i]
• The corrent condition is: i == -1:
This indicate that we went over all the elements in the list
Recursive Sum – alternative solution
Recursive Sum – alternative solution
Are we done?

• We Changed our implementation, but the users of


rec_sum still use the previous version with a single
parameter.
• Do the users need to know about the new parameter? It’s
a matter of our implementation.
Recursive Sum – alternative solution
• Our solution: a helper function

The users don’t know this function,


they only know rec_sum

When we call rec_sum_helper


we need to send the index of
.the last item in the list
If the list has 3 elements, the
index of the last item is 2,
therefore we use
len(lst) - 1
Example: Odd-Even

• Given a function odd(n)


• Odd n - return True, Even n – return False
• Write a function even(n) that:
• Even n - return True, Odd n – return False
• This is easy!

70
Odd-Even

71
Odd-Even

Is this implementation correct?

72
Odd-Even

73
Odd-Even

We never return False!

74

You might also like