COMP S265F Design and Analysis of Algorithms
Lab 2: Recursive Algorithms
In this lab, we will review the algorithm design technique “recursion” and study how to prove the correctness
of a recursive algorithm using mathematical induction. We will also introduce the syntax of defining classes in
Python, and analyze the time complexities of different algorithms.
1. Recursive algorithm
Recursion is a method of solving a problem where the solution depends on solutions to smaller instances
of the same problem. An recursive algorithm is an algorithm that applies recursion. Below is an example
of a recursive algorithm that finds the sum of integers from 1 to an user-specified positive integer n:
1 from sys import stdin
2
3 def print_sum():
4 """Reads a user-specified positive integer n,
5 and then prints the sum from 1 to n."""
6
7 n = int(stdin.readline()) # n is a positive integer
8 print(f"When n = {n}, 1 + 2 + 3 + ... + n = {sum(n)}.")
9
10 def print_sum2(n):
11 """print the sum from 1 to n."""
12 print(f"When n = {n}, 1 + 2 + 3 + ... + n = {sum(n)}.")
13
14 def sum(n):
15 if n == 1:
16 return 1
17 else:
18 return n + sum(n-1)
19
20 if __name__ == "__main__": # Allows You to Execute Code When the File Runs as a Script, but
Not When It's Imported as a Module
21 print(print_sum.__doc__)
22 print_sum()
Python docstring. A multi-line string in Python can be defined by surrounding the string with triple
quotes or triple double-quotes. The main function above has a docstring, which is a string literal occurring as
the first statement in the definition of a module, function, class, or method, and providing a short description of
the function. Docstrings are convenient for documentation, and can be accessed as a special attribute __doc__.
Python global variable __name__. It refers to the entry point to your program. If you run the program
directly, then it equals "__main__". Otherwise, it equals the program name that you import the module by.
Therefore, the code under the if-block will run only when you run the program directly.
Structure of a recursive function. A recursive function is composed of the following two components:
1. Base case: For simple input, the result can be returned directly.
2. Recursive step/Recurrence: For large input, the result is obtained using the solution on smaller input.
Due to this simple structure, a recursive function is easy to debug, implement, and comprehend. The structure
of a recursive function resembles that of a mathematical induction proof, so its correctness can be easily proved
by mathematical induction.
1
Theorem 1. The function sum(n) correctly returns the sum from 1 to n for any positive integer n.
Proof. We prove the statement by induction on n.
Base case: When n = 1, the if-block is run. Then, sum(n) = 1, which is the correct sum from 1 to n = 1.
Induction step. Assume that sum(k) returns the correct sum from 1 to k for some positive integer k,
i.e.,
k
sum(k) = 1 + 2 + 3 + · · · + k =
X
i.
i=1
When n = k + 1, we have n = k + 1 ≥ 1 + 1 = 2. Therefore, the else-block will be run. Then,
sum(k+1) = (k + 1) + sum(k) (by the definition of sum)
k
X
= (k + 1) + i (by the induction hypothesis)
i=1
k+1
X
= i.
i=1
2. Python class
The syntax for defining classes in Python is straightforward. The first argument of all instance methods is self,
which represents the instance of the class. In line 6 of the example below, self.n is an instance variable while
n is only a local variable. Similarly, you need to call an instance method on a class instance, e.g., self.sum in
line 10, and s.result in line 25.
1 from sys import stdin
2
3 class Summation:
4 # Constructor
5 def __init__(self, n):
6 self.n = n # Create an instance variable
7
8 # Instance method 1
9 def result(self):
10 return self.sum(self.n)
11
12 # Instance method 2
13 def sum(self, k):
14 if k == 1:
15 return 1
16 else:
17 return k + self.sum(k-1)
18
19 def main():
20 """Reads a user-specified positive integer n,
21 and then prints the sum from 1 to n."""
22
23 n = int(stdin.readline()) # n is a positive integer
24 s = Summation(n) # Create a Summation object
25 print(f"When n = {n}, 1 + 2 + 3 + ... + n = {s.result()}.")
26
27 if __name__ == "__main__":
28 print(main.__doc__)
29 main()
2
3. Exercises
Question 1. The factorial of a positive integer n, denoted by n!, is the product of all integers from 1 to n.
By definition, 0! = 1.
(a) Write a recursive function fac(n) (with two base cases) to compute n! for any integer n ≥ 0.
(b) Prove the correctness of fac(n) using mathematical induction.
Question 2. Using both the original and improved Euclid’s Algorithm, find the greatest common divisor
(g.c.d.) of the following numbers.
(a) 48, 36
(b) 133, 728
Question 3. Complete the following Python recursive function of the Euclid’s algorithm.
1 def gcd(a, b):
2 if a == b:
3 # return ...
4 elif a > b:
5 # return ...
6 else:
7 # return ...