L18 19 20 Recursion
L18 19 20 Recursion
Md Shad Akhtar
IIIT-Delhi
Functions - Recap
● Functions are defined with def <fn-name> (<parms>):
● The main program becomes more of a coordinator - with much of the work being done
in functions
Functions - Use
● What would be the output of following two codes segments?
● But body of a function can call another function declared below it - as body
executed only when function called (as call will originate from main - all functions
declared before main would have been seen by the interpreter)
Recursion
● Recursive definition is one where the defined term is used in the definition
● A function calls itself.
● A recursive algorithm uses itself to solve one or more smaller identical problems.
● All recursive definitions must have:
● Base case: Solution is know – without recursion (e.g. empty list).
● Recursive part: Problem is expressed as a smaller version of the problem itself.
Recursive algorithm
● Searching for a word in a dictionary, i.e., search(‘program’, D) – assume you don’t have any
markers/index
● Based on the first character of the word, we make a guess and goto to some page in the middle.
● If words on the opened page have the first character greater than the first character of the
queried word in alphabetical order
● Query word must be before that opened page.
● Make a new search only on the left side of the dictionary, i.e., search(‘program’, DL),
where DL ⊆ D
● Same problem but with a smaller dictionary or narrower search space.
● If words on the opened page have the first character lesser than the first character of the
queried word in alphabetical order
● Query word must be after that opened page.
● Make a new search only on the right side of the dictionary, i.e., search(‘program’,
DR), where DR ⊆ D
● Same problem but with a smaller dictionary or narrower search space.
● Repeat the process until we find the desired word or search space becomes empty.
Recursion in Python functions
● Python allows recursive functions, i.e., a function can call itself
● Not all languages allowed recursive functions
● Most modern programming languages allow it
● Every recursive call should bring the function call closer to the base case.
● If the recursive part is such that the base case will not be reached - then we have
infinite recursion (the program will never end).
Recursion - Example
if x = 0,
else: 1 f(x = 1) 1
return 1 + f(x-1) +
1 f(x = 0) 0
● Not defined.
● Remember end-user is not so intelligent, if this happens,
you (programmer) have to bear all the blame!
○ Checks must be there.
Factorial of a number
def factorial(n):
factorial(n = 4) 24
if n < 0: #invalid case
*
print(‘Not defined’)
return 0 4 factorial(n = 3) 6
if n <= 1: #base case *
return 1
else: 3 factorial(n = 2) 2
return (n * factorial(n-1)) *
n = 4
2 factorial(n = 1) 1
print(factorial(n))
Execution of recursive functions
● Recursive call is similar to a function calling another function - a recursive call is treated as a regular fn call
● When a function is called, a separate space (called frame) is allocated to this call where all local vars
(incl parms) reside - function statements operate on these
● When a function returns (i.e. completes its execution) - frame is released and local vars disappear
n=4
def factorial(n): Main program (global) variable
if n <= 1:#base case factorial
return 1
On factorial(4) call n=4
else:
❌
On return
return (n * factorial(n-1))
On factorial(3) call n=3
❌
On call
n = 4
print(factorial(n))
On factorial(2) call n=2
❌
● Many data structures (lists, trees, etc) are naturally recursive - for operations on them
recursion is most natural
● A binary tree: root node + l tree + r tree Recursive vs Iterative
● A list: one item, followed by a list Which of these solutions are better and why?
0, if n = 0,
0 1 1 2 3 5 8 13 …. fib(n) = 1, if n = 1
def fib(n):
if n == 0 or n == 1: #base case
return(n)
else:
return(fib(n-1) + fib(n-2))
More recursive problems - Fibonacci
● Fibonacci series: A number in series is the sum of last two numbers in the same series
fib(n = 4) 3
0 1 1 2 3 5 8 13 …. +
fib(n = 3) 2 fib(n = 2) 1
+ +
1, 2, 4, 8, 9, 5, 2, 6, 7
More recursive problems - Fibonacci
● The current solution is not effective
○ We need three fib(1) calls, two fib(0) and fib(2) calls
fib(n = 4) #1
● How to make it effective?? +
○ Save the computation, to be reused later.
fib(n = 3) #2 fib(n = 2) #3
● Home exercise (ungraded)
+ +
○ You’ll need some data type to store intermediate
results
fib(n = 2) #4 fib(n = 1) #5 fib(n = 1) #6 fib(n = 0) #7
fib(n = 1) #8 fib(n = 0) #9
Example
● Given a pair of recursive functions,
● Write the outcome of the following statements:
● print(f(2) == g(0)) def f(n):
if n == 0:
● print(g(2) + f(2) == 0)
return 1;
● print(g(4) + g(1) == 0)
return f(n-1) + g(n-1);
● print(f(3) + f(0) == 0) def g(n):
● Draw execution (recursion) tree for f(2) and if n == 0 :
compute its value. return 1;
● Draw execution (recursion) tree for g(2) and return g(n-1) - f(n)
compute its value.
More recursive problems: Palindrome
● A piece to text, in which the sequence of characters in both forward and reverse
directions are exactly the same.
● nitin True
P(w =‘nitin’, 0, 4 )
● was it a cat I saw and
True
w[0] == w[4] P(w = ‘nitin’, 1, 3)
True
‘n’ == ‘n’
and
Linear search: Search until we get the item or no Binary search: Divide the space in two parts and
checks only one part everytime, until we get the item or
more space remains
no more space remains
Linear Search
0 1 2 3 4
1 2 4 5 32
Binary_search(lst, 1, 1, item)
Compute mid and check. Update start and
end and call recursive function accordingly.
Binary Search: Recursive solution
def b_search(A, start, end, item):
if start > end:
return False
else:
mid = (start+end) // 2
if A[mid] == item:
return True
elif A[mid] < item:
start = mid + 1
else:
end = mid - 1
return b_search(A, start, end, item)
A = [1, 2, 3, 5, 32]
print('Item found:', b_search(A, 0, 4, 32)) # True
print('Item found:', b_search(A, 0, 4, 21)) # False
More recursive problems: Tower of Hanoi
Given 3 rods (A, B, C) and n disks.
Rules:
1. Only one disk can be moved at a time.
2. A disk can only be moved if it is the uppermost disk in the stack.
3. Larger disk cannot be placed on top of a smaller disk.
ToH Subproblem: Move 1 disk from A to B
A B C A B C
Subproblem
We know how to move one disk!!
Subproblem
A B C A B C
We know how to move one or two disks!!
Subproblem
A B C A B C
We know how to move one, two, or three disks!!
A B C A B C
Tower of Hanoi
Rules:
1. Only one disk can be moved at a time.
2. A disk can only be moved if it is the uppermost disk in the stack.
3. Larger disk cannot be placed on top of a smaller disk.
● Usually the parameter value of the recursive call will be different from the original call - and
movement towards the direction that the base class will be reached
● Remember, each function call take space in the memory and can lead to a Stack Overflow Error, if
you are not careful.
● To prevent this Python stops recursion at the 1000th recursive call.
● This limit can be modified using the sys.setrecursionlimit(<limit>) function of the sys module.
To be used with caution.