Professional Documents
Culture Documents
Post - 2030 L4
Post - 2030 L4
Post - 2030 L4
EECS 2030
Lecture 4 :: Recursion
Think recursively
1
2020-09-23
Think
recursively
2
2020-09-23
Recursion
• Recursion is the process of defining a problem (or the solution to a
problem) in terms of (a simpler version of) itself.
▪ number of characters in a string is 1 + number characters in the
remaining string
o lengh("ABCD") = 1 + length("BCD")
▪ a × b can be solved by a + a × (b-1)
▪ ab can be solved by a × ab-1
▪ sum of n numbers is sum of first and rest
o sum(4,8,7,5) = 4 + sum(8,7,5)
▪ Max value in a list is the larger of first and max of rest list
▪ Factorial n can be defined/solved as n! = n * (n-1)!
▪ Fibonacci sequence is defined as: F(i) = F(i-1) + F(i-2)
5
Why recursion?
• Solves some problems more naturally than
iteration
▪ In computer science, some problems are more easily
solved by using recursive functions.
o Tower of Hanoi
3
2020-09-23
Recursive Definitions
• Every recursive algorithm involves at least 2 cases:
▪ Base case(s).
▪ Recursive calls/cases.
• General case:
▪ Case in recursive definition in which a smaller version of itself
is called
▪ Usually by changing the parameter(s).
▪ Must eventually be reduced to a base case
o Progress toward base case
4
2020-09-23
Recursion
10
5
2020-09-23
Recursion
else
getIn (house on the right)
pick up key for A
open A;
}
11
11
Recursion
“To get into my house
I must get the key from a smaller house
length(“ABCD”)
= 1 + length(“BCD”)
= 1 + ( 1 + length(“CD”))
= 1 + ( 1 + ( 1 + length(“D”))) Can save restL
=121 + ( 1 + ( 1 + (1+ (1+length(“”) )))
=1+ (1+ ( 1 + (1+ (1+0) ))) = 4
12
6
2020-09-23
Recursion
“To get into my house
I must get the key from a smaller house
length(“ABCD”)
= 1 + length(“BCD”)
= 1 + ( 1 + length(“CD”))
= 1 + ( 1 + ( 1 + length(“D”)))
= 1 + ( 1 + ( 1 + (1+ length(“”) )))
=13 1 + ( 1 + ( 1 + (1+ 0 ))) = 4
13
Recursion
“To get into my house
I must get the key from a smaller house
length(“ABCD”)
= 1 + length(“BCD”)
= 1 + ( 1 + length(“CD”))
= 1 + ( 1 + ( 1 + length(“D”)))
= 1 + ( 1 + ( 1 + (1+ length(“”) )))
=14 1 + ( 1 + ( 1 + (1+ 0 ))) = 4
14
7
2020-09-23
Recursive Methods
• Caller “pause” on method call
15
2
int a = length("ABCD") static int length ("CD")
{
System.out.println(a); if ("CD".equals("")
return 0;
return 1 + length("CD".substring(1));
}
16
16
8
2020-09-23
Recursion - example1
• Think/define iteratively
17
17
Recursion
• Think/define recursively `
1 if n = 0
factorial (n) =
n factorial (n − 1) otherwise
9
2020-09-23
Visualizing Factorial
Recursion trace tree for factorial(4) :
return 4 * 6 = 24 final answer
call
factorial (4 )
call return 3 *2 = 6
factorial (3 )
call return 2 *1 = 2
factorial (2 )
call return 1 *1 = 1
factorial (1 )
call return 1
factorial (0 )
19
24 2
static int factorial (2)
{
int a = factorial(4) if(2 == 0) /* base case */
return 1;
return 2 * factorial (2 – 1);
}
n=3 return ? LN = 3 1
static int factorial (0)
n=4 return ? LN = 3 {
if(0 == 0) /* base case */
call/execution/program stack return 1;
return n * factorial (0 – 1);
}
20
10
2020-09-23
int a = factorial(4)
a factorial(4)
main()
21 call/execution/program stack
21
int a = factorial(4)
a factorial(4)
22 call/execution/program stack
22
11
2020-09-23
int a = factorial(4)
a factorial(4)
n 3
result 3 * factorial(2)
23 call/execution/program stack
23
int a = factorial(4)
a factorial(4)
800 factorial method
n 2
result 2 * factorial(1)
n 3
result 3 * factorial(2)
fact(2)
fact(3) 600 factorial method
fact(4)
n 4
main()
result 4 * factorial(3)
24 call/execution/program stack
24
12
2020-09-23
result 1 * factorial(0)
a factorial(4)
800 factorial method
n 2
result 2 * factorial(1)
n 3
result 3 * factorial(2)
fact(1)
fact(2)
fact(3) 600 factorial method
fact(4)
n 4
main()
result 4 * factorial(3)
25 call/execution/program stack
25
result 1 * factorial(0)
a factorial(4)
800 factorial method
n 2
result 2 * factorial(1)
n 3
26 call/execution/program stack
26
13
2020-09-23
result 1 * 1
a factorial(4)
800 factorial method
n 2
result 2 * factorial(1)
n 3
result 3 * factorial(2)
fact(1)
fact(2)
fact(3) 600 factorial method
fact(4)
n 4
main()
result 4 * factorial(3)
27 call/execution/program stack
27
int a = factorial(4)
a factorial(4)
800 factorial method
n 2
result 2 * 1
n 3
result 3 * factorial(2)
fact(2)
fact(3) 600 factorial method
fact(4)
n 4
main()
result 4 * factorial(3)
28 call/execution/program stack
28
14
2020-09-23
int a = factorial(4)
a factorial(4)
n 3
result 3 * 2
29 call/execution/program stack
29
int a = factorial(4)
a factorial(4)
30 call/execution/program stack
30
15
2020-09-23
int a = factorial(4)
a 24
main()
31 call/execution/program stack
31
Recursion example 2
• Think/define non-recursively b4 = b * b * b * b
32
16
2020-09-23
Recursion
• Think/define recursively `
“To get into my house
I must get the key from a smaller house
bn = b* bn-1
1 if n = 0
power (base, n) =
base power (base, n − 1) otherwise
33
8 }
4
16 static int power (2, 2)
{
if(2 == 0) /* base case */
int a = power(2, 4)
return 1;
else
return 2 * power (2, 2 – 1);
}
2
static int power (2, 1)
{
base=2 n=0 return 1
if(n == 0) /* base case */
return 1;
base=2 n=1 return ? LN = 4
else
base=2 n=2 return ? LN = 4 return 2 * power (2, 1 – 1);
}
base=2 n=3 return ? LN = 4
static int power (2, 0)
base=2 n=4 return ? LN = 4 1
{
if(0 == 0) /* base case */
call/execution/program stack return 1;
else
return n * power (2, 0 – 1);
34
17
2020-09-23
Recursion
• Think/define recursively `
“To get into my house
I must get the key from a smaller house
1 if n = 0
power (base, n) =
base power (base, n − 1) otherwise
35
Recursion
• Think/define recursively `
“To get into my house
Anther way to reduce to smaller/sub-problem I must get the key from a smaller house
1 𝑖𝑓 𝑛 𝑖𝑠 0
𝑛 𝑛 if 𝑛 = 0
𝑝𝑜𝑤𝑒𝑟(𝑏𝑎𝑠𝑒, 𝑛) = ቊ 𝑝𝑜𝑤𝑒𝑟(𝑏𝑎𝑠𝑒, ) ⋅ 𝑝𝑜𝑤𝑒𝑟(𝑏𝑎𝑠𝑒, 2 ) 𝑖𝑓 𝑛 𝑖𝑠 𝑒𝑣𝑒𝑛
𝑝𝑜𝑤𝑒𝑟(𝑏𝑎𝑠𝑒, 𝑛/2)2 ⋅ 𝑝𝑜𝑤𝑒𝑟(𝑏𝑎𝑠𝑒, 𝑛/2)
𝑛−1 𝑛−1
𝑏𝑎𝑠𝑒 ⋅ 𝑝𝑜𝑤𝑒𝑟 𝑏𝑎𝑠𝑒, ⋅ 𝑝𝑜𝑤𝑒𝑟 𝑏𝑎𝑠𝑒, 𝑖𝑓 𝑛 𝑖𝑠 𝑜𝑑𝑑
2 2
int power (int base, int n) // assume n >= 0
{ 2 4 = 2 2 * 22
if(n == 0) /* base case */ 25 = 2 * 22 * 22
return 1;
else{
if (n%2==0) { // n is even
int powHalf = power (base, n/2);
return powHalf * powHalf; } return power (base, n/2)*
power (base, n/2);
else { // n is odd
int powHalf = power (base, (n-1)/2);
36
return base * powHalf * powHalf;}}
36
18
2020-09-23
37
38
19
2020-09-23
int[] a = {2,0,3,0}
return 0 +2 = 2 final answer
countZeros(a, 0); call
countZeros (a,0)
call return 1 +1 = 2
countZeros (a,1)
call return 0 +1 = 1
countZeros (a,2)
39
• Examples:
▪ number of zeros in 20300 is number of zeros in 2030
plus 1
▪ number of zeros in 20031 is number of zeros in 2003
40
40
20
2020-09-23
/**
* Counts the number of zeros in an integer n
*/
countZeros(n) :
41
/**
* Counts the number of zeros in an integer n
*/
countZeros(n) :
else
return countZeros(n / 10)
42
21
2020-09-23
Always start by …
• Establishing the base case(s) !!
▪ what is the smallest version(s) of the problem??
▪ when should the recursion stop?
o base case #1 : n == 0
return 1
43
43
numberOfZeros method
public static int numberOfZeros(int n)
{
int zeroCount;
Boolean lastDigitZero = (n%10==0);
base cases, n <10
if (n==0) - always first – if hit, will
zeroCount = 1; force return.. stops
recursion
else if (n < 10) // 1~9
zeroCount = 0; // no zeros MUST BE EXHAUSTIVE
(cover every case that
has a solution)
else if (lastDigitZero)
zeroCount = 1 + numberOfZeros(n/10);
else // n%10 != 0
zeroCount = 0 + numberOfZeros(n/10);
44 return zeroCount;
}
44
22
2020-09-23
numberOfZeros method
public static int numberOfZeros(int n)
{
if (n==0)
return 1;
else if (n < 10) // and not 0
return 0; // 0 for no zeros
if (n%10 == 0)
return 1 + numberOfZeros(n/10);
else
return numberOfZeros(n/10);
}
Shorter version
45
45
numberOfZeros (20301)
call return 1 +1 = 2
numberOfZeros ( 2030 )
call return 0 +1 = 1
countZeros (203)
countZeros (20)
call return 0
countZeros (2 )
46
23
2020-09-23
Example 4
Printing n of Something
• suppose you want to implement a method that prints out
n copies of a string, one copy per line
printIt("*", 4)
*
*
*
47 *
47
48
48
24
2020-09-23
Recursion
public static void printItToo(String s, int n) {
• a method that calls
if (n itself
== 0) is
{ called a recursive method
return;
• a recursive method
} solves a problem by repeatedly
reducing the problem
else { so that a base case can be
System.out.println(s);
reached printItToo(s, n - 1); // method invokes itself
}
}
printItToo("*", 5)
* printItToo ("*", 4)
* printItToo ("*", 3)
* printItToo ("*", 2)
* printItToo ("*", 1)
printItToo ("*", 0) base case Notice that a base case is
*
eventually reached.
49
49
Infinite Recursion
• if the base case(s) is missing, or never reached, a
recursive method will run forever (or until the computer
runs out of resources)
printItForever("*", 1)
* printItForever("*", 0)
* printItForever("*", -1)
* printItForever("*", -2) ...........
50
50
25
2020-09-23
Printing n of Something
• suppose you want to implement a method that prints out
n+(n-1)+(n-2) ..1 copies of a string
▪ n times first line, n-1 times second line, n-2 times 3rd line…
51
52
26
2020-09-23
printItToo("*", 5)
***** printItToo ("*", 4)
**** printItToo ("*", 3)
*** printItToo ("*", 2)
** printItToo ("*", 1)
* printItToo ("*", 0) base case
53
53
for(int i=0;i<n;i++)
System.out.print(s);
System.out.println();
54
}
54 }
27
2020-09-23
printItToo("*", 5)
printItToo ("*", 4)
printItToo ("*", 3)
printItToo ("*", 2)
printItToo ("*", 1) *
printItToo ("*", 0) **
***
****
*****
What is the output? Same as 4b?
55 Anything printed, in the first 5 recursive function calls?
55
56
28
2020-09-23
57
57
System.out.println(s);
}
}
58
58
29
2020-09-23
Fibonacci Numbers
• the sequence of additional pairs
▪ 0, 1, 1, 2, 3, 5, 8, 13, ...
are called Fibonacci numbers
▪ Each number in the series is sum of two previous numbers
• base cases
▪ F(0) = 0
▪ F(1) = 1
• recursive definition
▪ F(n) = F(n – 1) + F(n – 2)
59
59
60
60
30
2020-09-23
Recursive Fibonacci
• example: compute the n’th Fibonacci number
61
61
1 1
static int fib (3) { static int fib (2) {
if (n == 0) return 0; if (n == 0) return 0;
else if (n == 1) return 1; else if (n == 1) return 1;
return fib(3 - 1) + fib(3 - 2); return fib(2 - 1) + fib(2 - 2);
1 0 1 0
static int fib (2) { static int fib (1) { static int fib (1) { static int fib (0) {
if (n == 0) return 0; if (n == 0) return 0; if (n == 0) return 0; if (n == 0) return 0;
else if (n == 1) return 1; else if (n == 1) return 1; else if (n == 1) return 1; else if (n == 1) return
return fib (2-1) + fib (2-2); return fib (1-1) + … return fib (1-1) + … return fib (1-1) + …
1 0
static int fib (1) { static int fib (0) {
if (n == 0) return 0; if (n == 0) return 0; F(4)
else if (n == 1) return 1; else if (n == 1) return 1; F(3)
return fib (1-1) + … return fib (1-1) + …
F(2)
F(1)
F(0)
F(1)
F(2)
F(1)
Be careful about the call sequence F(0)
62 You should know that (be able trace)
62
31
2020-09-23
F(4)
public static int fibonacci(int n) {
F(3)
if (n == 0)
return 0; F(2)
else if (n == 1) { F(1)
return 1; F(0)
F(1)
int f = fibonacci(n - 1) + fibonacci(n - 2); F(5) F(2)
return f;
F(1)
}
F(0)
F(3)
F(4) F(3) F(2)
F(1)
F(0)
F(1)
F(3) F(2) F(2) F(1)
1
F(1) F(0)
1 0
63
Recursive Definitions
• Recursion
▪ Process of solving a problem by reducing it to smaller versions
of itself
▪ It can be either *
o Decrease and conquer
❖ Reduce a problem of size n into a sub-problem of size n-b
❖ factorial(), length(), power(), zeros in array/string/number
64
32
2020-09-23
65
2, 6 21+46
3, 5 4+42
4, 4 33+9
5, 3 3+6
6, 2 6
7, 1
66
33
2020-09-23
67
A = (0,4)
2 7 6 21 4 33 3 6 (0,2)
(0,1)
A,0,8 82 (1,1)
(2,2)
(2,1)
A,0,4 36 A,4, 4 46 (3,1)
(4,4)
(4,2)
0, 2 9 2, 2 27 4, 2 37 6, 2 9 (4,1)
(5,1)
0, 1 1, 1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 (6,2)
(6,1)
2 + 7 + 6 + 21 + 4 + 33 + 3 + 6 (7,1)
68
34
2020-09-23
A = 2 7 6 21 4 33 3 6
69
Towers of Hanoi
Problem
• Invented by Edouard Lucas, in 1883
• Given a tower of n disks, initially stacked in increasing
size on one of three pegs, the objective is to transfer the
entire tower to one of the other pegs, moving only one
disk at a time and never a larger one onto a smaller.
• Play it at
http://www.web-games-online.com/towers-of-
hanoi/index.php
70
35
2020-09-23
Move 2 Move 3
71
Move 3
Move 4 Move 5
4: 15 7: 127
5: 31 8: 255 Probably not possible non-recursively
6: 63 9: 511
72
36
2020-09-23
73
74
37
2020-09-23
75
4: 15
5: 31
6: 63
M(n) = 2 M(n-1) + 1
7: 127
8: 255
M(n) = 2n – 1
9: 511
… Big O = O(2n)
64:264 -1
76
38
2020-09-23
Summary of recursion
• Problems solved by recursion, can be solved by iterative methods too.
▪ Recursive solution usually is cleaner, short. E.g., Tower of Hanoi
▪ More efficient? See complexity later.
• Don’t expect that you can solve a recursive algorithm straight away.
▪ Need quite some practice
77
77
Summary of recursion
78
78
39