CS1010S-Lec-03 Recursion, Iteration
CS1010S-Lec-03 Recursion, Iteration
Lecture 3
Recursion, Iteration
30 Aug 2023
Admin Matters
- Contest in the next week
- Once you start, you should finish within 90 mins.
- Consider it as a prep for the midterm exam.
- The contest will be open from 10am to 4pm on Sat 9th Oct
- If you are unable to attempt in this time window, let us know by
this Saturday 2359.
- Do not plagiarise!
Don’t pay for
notes/exam
papers!
NUS Course Material
Ethical Behaviour and Respecting Copyright
All course participants (including permitted guest students) who have access to the course
materials on LumiNUS or any approved platforms by NUS for delivery of NUS modules are not
allowed to re-distribute the contents in any forms to third parties without the explicit consent
from the module instructors or authorized NUS officials
Examples of what is disallowed
• No posting on any websites (except otherwise explicitly allowed)
• No selling of material
• No sharing of questions/answers which could lead to cheating/plagiarism
Recap
Rewrite:
𝑛 × 𝑛−1 !, 𝑛 >1
𝑛! = ቊ
1, 𝑛=1
Factorial
𝑛 ×𝑓 𝑛−1 , 𝑛 >1
𝑓(𝑛) = ቊ
1, 𝑛=1
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n – 1)
Recursion
def factorial(n):
if n == 1: terminating condition
return 1 (base case)
else:
return n * factorial(n – 1)
recursive call
Function that calls itself is called a recursive function
Ingredients for recursion
1. Base Case
Does involve a recursive call!
Has trivial answer
2. Recursive Step
Connects solution at to its subproblem!
def factorial(n):
if n == 1:
return 1
Recursive Factorial
else:
return n * fact(n – 1)
1
factorial(4)
deferred calls 1
factorial(4) 2
= 4 * factorial(3)
= 4 * 3 * factorial(2) 2
= 4 * 3 * 2 * factorial(1)
= 4 * 3 * 2 * (1) 3
= 4 * 3 * (2)
= 4 * (6) 6
= 24 24
4
Factorial: Another way! res = 1
counter = 1
res = 1
res = 1 * 2
res = 1 * 2 * 3
res = 1 * 2 * 3 * 4 F
counter <= n
…
T
def factorial(n):
res, counter = 1, 1
res = res * counter
while counter <= n:
res = res * counter
counter = counter + 1
return res counter = counter + 1
Iterative Process
res counter
def factorial(n):
1 1
res, counter = 1, 1
while counter <= n: 1 2
res = (res * counter) 2 3
counter = counter + 1 6 4
return res
24 5
factorial(5)
No deferred calls!
while loop while <expression>:
<while_body>
expression
Predicate (condition) to stay within the loop
F
<cond>
body T
if predicate is True
outside
Yet another way! non-inclusive.
Up to n.
def factorial(n):
res = 1
for counter in range(2, n+1):
res = res * counter
return res
def factorial(n):
res, counter = 1, 1
while counter <= n:
res = res * counter
counter = counter + 1
return res
for loop for <var> in <sequence>:
<for_body>
sequence
a sequence of values
for each
var item in
seq
variable that take each value in the sequence
The seq
is over
body for_body
statement(s) that will be evaluated for outside
each value in the sequence
range function Examples
F
j == 3
T
print(“done”)
continue
for j in range(10): 1 for j in
if j % 2 == 0: 3 [0…9]
continue 5
The seq
print(j) 7 T j is is over
print("done") 9 even
done F
print(j)
print(“done”)
Example 2: Exponentiation 𝑛𝑚−1
𝑛𝑚 = 𝑛 × 𝑛 × 𝑛 × … × 𝑛
Rewrite:
𝑛 × 𝑛𝑚−1 , 𝑚 > 0
𝑛𝑚 =ቊ
1, 𝑚=0
Exponentiation: Recursion
def power(n, m): def factorial(n):
if m == 0: if n == 0:
return 1 return 1
else: else:
return n * power(n, m – 1) return n * factorial(n – 1)
Notice any
similarity?
Exponentiation: Iteration
def power(n, m): def factorial(n):
res, counter = 1, 1 res, counter = 1, 1
while counter <= m: while counter <= n:
res = (res * counter)
res = res * n
counter = counter + 1
counter = counter + 1 return res
return res
power(2, 4) factorial(5)
res = 1 res = 1
res = 1 * 2 res = 1 * 2
res = 1 * 2 * 2 res = 1 * 2 * 3
res = 1 * 2 * 2 * 2 res = 1 * 2 * 3 * 4
res = 1 * 2 * 2 * 2 * 2 res = 1 * 2 * 3 * 4 * 5
Typical structure of recursion
def fn(n):
if <base_cond>:
return <base_val> Try to express the
else: problem in the
return <recur_formula> recursive way!
Examlple 3: Fibonacci Numbers
Leonardo Pisano Fibonacci (12th century) is credited for
the sequence:
0, 1, 1, 2, 3, 5, 8, 13, 21, …
fib(4) fib(3)
1 1 0 1 0
fib(1) fib(0)
1 0
leaves
How about iteration?
def fib(n):
if (n == 0): a b c
a b c
return 0 0 1 1 2 3 5
elif (n == 1): a b c
a b
return 1
a, b = 0, 1
Observations:
while <cond>:
c = a + b
??? - Next a is current b
- Next b is current c
How about iteration?
def fib(n): Was this iteration
if (n == 0): as easy as
return 0 factorial/power?
elif (n == 1):
return 1
a, b = 0, 1
a, b = b, a + b
while n > 1:
# in this case answer is b
c = a + b
a = b
a, b = b, c
b = c
n = n – 1
return c
Questions
Recursive formula to count the number of digits in a
number.
Rules.
1. Can only put one disc at a time
2. Cannot put larger disc over a smaller disc
Towers of Hanoi
Rules.
1. Can only put one disc at a time
2. Cannot put larger disc over a smaller disc
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
Towers of Hanoi
A B C
https://pollev.com/ashishdandekar
Counting Change Problem
How many ways to make change for $1, using
coins
50¢, 20¢, 10¢, 5¢, 1¢ (assuming unlimited number of coins)
e.g. 50¢ + 50¢
50¢ + 20¢ + 20¢ + 10¢
20¢ + 20 ¢ + 20¢ + 20¢ + 20¢
etc.
Recursion
1. Express (divide) the problem into smaller
similar problem(s)
2. Solve the problem for a simple (base) case
Understand the problem
What are the inputs?
- The amount: a (in cents).
- Types-of-coins: {𝑑1 , 𝑑2 , … , 𝑑𝑛 }
e.g. only 50¢ and 20¢
• 50 + 50
• 50 + 20 + 20 + 10 • 20 + 20 + 20 + 20 + 20
• 20 + 20 + 20 + 20 + 10
• 50 + 20 + 10 + 10 + 10
+10 • ….
• …
50¢ + 50¢ $1
{50, 20, 10, 5 ,1} {20, 10, 5 ,1}
In general
𝑎
{𝑑1, 𝑑2, … , 𝑑𝑘 }
𝑑1 + 𝑎 − 𝑑1 𝑎
{𝑑1, 𝑑2, … , 𝑑𝑘 } {𝑑2, … , 𝑑𝑘 }
Base Case
If amount is zero
- There is exactly 1 way!
COINS DENOMINATION
5 50
4 20 abstraction
3 10
2 5
1 1
Python function
def cc(amount, kinds_of_coins):
if amount == 0:
return 1
elif (amount < 0) or (kinds_of_coins == 0):
return 0 Using 1 coin for
first kind
else:
return cc(amount – first_denomination(kinds_of_coins),
kinds_of_coins) +
cc(amount, kinds_of_coins-1)
Without using first
def first_denomination(kinds_of_coins): kind of coin
… <left as an exercise>
def count_change(amount)
return cc(amount,5)
Iteration
Counting change is easily formulated via recursive
process.
https://pollev.com/ashishdandekar
Summary
• Recursion
- Solve the problem for a simple (base) case
- Express (divide) a problem into one or more
smaller similar problems
• Iteration:
- while and for loops
Summary
• All problems that can be solved using recursion
can also be solved using iteration.
Naïve Solution.
1. Set GCD to 1.
2. Start with 1.
3. Check for every number if it divides and b. If it
does, set it as GCD.
4. Continue until you reach a or b.
Greatest Common Divisor
Euclid’s Algorithm.
32 = 7 ∗ 4 + 4
Given two numbers a and b, where
𝑎 = 𝑏𝑄 + 𝑟 (the remainder of the division).
Then we have,
𝐺𝐶𝐷 𝑎, 𝑏 = 𝐺𝐶𝐷 𝑏, 𝑟 , ∀𝑎, 𝑏 > 0
𝐺𝐶𝐷(𝑎, 0) = 𝑎
Greatest Common Divisor
def gcd(a, b): 𝐺𝐶𝐷 𝑎, 𝑏 = 𝐺𝐶𝐷 𝑏, 𝑟 , ∀ 𝑎, 𝑏
if (b == 0): 𝐺𝐶𝐷(𝑎, 0) = 𝑎
return a
else:
return gcd(b, a % b)
GCD(206,40) = GCD(40,6)
= GCD(6,4)
= GCD(4,2)
= GCD(2,0)
= 2
Another Example
Exponentiation – another angle!
power(a, 13)
1 𝑒=0
𝑒
𝑒
𝑏 =൞ (𝑏 2 )2 𝑒 is even = a * power(a, 12)
𝑏 ⋅ 𝑏 𝑒−1 𝑒 is odd = a * power(b, 6) b = a*a
= a * power(c, 3) c = b*b
= a * c * power(c, 2)
= a * c * power(d, 1) d = c*c
= a * c * d * power(d, 0)