9 Recursion
9 Recursion
Recursio
Recursi
Recurs
Recur
Recu
Rec
Re
R
Methods that call themselves
• Consider 5! equates to 5 * 4 * 3 * 2 * 1
• This is an iterative example, as is the code:
public static long fact(int n)
{
long prod = 1;
for(int i=1; i<=n; i++)
prod *= i;
return prod;
}
• How would you define n! in an iterative fashion?
•
Methods that call themselves
• Consider 5! equates to 5 * 4 * 3 * 2 * 1
• This is an iterative example, as is the code:
public static long fact(int n)
{
long prod = 1;
for(int i=1; i<=n; i++)
prod *= i;
return prod;
}
• How would you define n! in an iterative fashion?
• n! = (n) * (n-1) * (n-2) * (n-3) * … * 3 * 2 * 1
n! = (n) * (n-1) * (n-2) * (n-3) * … * 3 * 2 * 1
• This is a lousy mathematical definition:
• It doesn’t work for n==1, 2, 3, 4, 5, or 6
• No mathematic definition should contain “…”
• Consider a definition of n! that is more
mathematically sound:
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
0! = 1
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 1 = 1
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1 = 2
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2 = 6
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4!
4! = 4 * 6 = 24
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 24 = 120
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4! and 0! = 1
So what is n!...
5! = 5 * (4 * 3 * 2 * 1)
Note that 4! = (4 * 3 * 2 * 1)
5! = 5 * 4! and 0! = 1
So what is n!...
n! = n * (n-1)! and 0! = 1
• This is a recursive definition:
• We define n-factorial by calling factorial in the next
easiest state (recursive call)
• We tell it when to stop, 0! = 1 (terminating case)
public static long fact(int n)
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
• there is no loop
• loop-like behavior is achieved by the method
calling itself inside of itself
• the method MUST know when to stop, which
is the terminating case.
public static long fact(int n) //5
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5)
public static long fact(int n) //5
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 * fact(4)
public static long fact(int n) //4
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4)
public static long fact(int n) //4
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3)
public static long fact(int n) //3
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3)
public static long fact(int n) //3
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 * fact(2)
public static long fact(int n) //2
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2)
public static long fact(int n) //2
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2 * fact(1)
public static long fact(int n) //1
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2*
fact(1)
public static long fact(int n) //1
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2*
fact(1) =
1 * fact(0)
public static long fact(int n) //0
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2*
fact(1) =
1 * fact(0)
=
1
public static long fact(int n) //1
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2*
fact(1) =
1*1=1
public static long fact(int n) //2
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 *
fact(2) =
2*1=2
public static long fact(int n) //3
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * fact(3) = 3 * 2 = 6
public static long fact(int n) //4
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 *
fact(4) = 4 * 6 = 24
public static long fact(int n) //5
{
if( n == 0) //terminating case, 0! = 1
return 1;
return n * fact(n – 1); //recursive call, n! = n * (n-1)!
}
fact(5) = 5 * 24 = 120
Recursive thinking
• First consider the terminating case:
– What is the most simple possible input such that the method
already knows the answer?
– For factorial, the easiest number to find the factorial of is zero.
fact(0) should return 1.
• Then, given complex input, what would be considered “one-
step-easier”.
– For factorial, fact(5) would be complex.
– One-step-easier than fact(5) would be fact(4).
• Now, how can you define the solution given complex input
by calling the method given “one-step-easier”?
– For factorial, fact(5) is equivalent to 5 * fact(4)
• Lastly, replace the complex input with the argument name.
– If fact(5) = 5 * fact(4), then fact(n) = n * fact(n-1)
void recursion
public static void doStuff(int n)
{
if(n >= 0)
{
System.out.println(n);
doStuff(n – 2);
}
}
Note: terminating case not implicitly stated, but…
If n < 0, the if statement is skipped and the method ends.
If we keep subracting 2 from n, the condition will eventually be
false and the method can stop.
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0)
{
System.out.println(n);
doStuff(n – 2);
}
}
output
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
doStuff(4)
{
System.out.println(n);
doStuff(n – 2);
}
}
output
6
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n);
doStuff(n – 2);
}
}
output
6
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
}
}
output
6
4
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
}
}
output
6
4
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
SOP(2)
} doStuff(0)
}
output
6
4
2
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
SOP(2)
}
doStuff(0)
}
output
6
4
2
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
SOP(2)
}
doStuff(0)
} SOP(0)
output doStuff(-2)
6
4
2
0
void recursion
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) SOP(6)
{ doStuff(4)
System.out.println(n); SOP(4)
doStuff(2)
doStuff(n – 2);
SOP(2)
}
doStuff(0)
} SOP(0)
output
6 doStuff(-2)
4
2
0
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0)
{
doStuff(n – 2);
System.out.println(n);
}
}
output
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{
//we will, in order, call
doStuff(n – 2); //doStuff(4) and then
System.out.println(n); //print the 6.
} //But we must finish
} //doStuff(4) before we
output //print the 6
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{
doStuff(n – 2);
System.out.println(n);
}
}
output
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); //we will, in order, call
System.out.println(n); //doStuff(2) and then
//print the 4.
}
//But we must finish
} //doStuff(2) before we
output //print the 4
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2);
System.out.println(n);
}
}
output
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); doStuff(0)
System.out.println(n); //we must finish
} //doStuff(0) before
//we print the 2
}
SOP(2)
output
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); doStuff(0)
System.out.println(n);
}
}
SOP(2)
output
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); doStuff(0)
System.out.println(n); doStuff(-2)
}
} SOP(0)
SOP(2)
output
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); doStuff(0)
System.out.println(n); doStuff(-2)
}
} SOP(0)
SOP(2)
output
SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2); doStuff(0)
System.out.println(n);
}
} SOP(0)
SOP(2)
output
0 SOP(4)
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{ doStuff(2)
doStuff(n – 2);
System.out.println(n);
}
}
SOP(2)
output
0 SOP(4)
2
SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0) doStuff(4)
{
doStuff(n – 2);
System.out.println(n);
}
}
output
0 SOP(4)
2
4 SOP(6)
void - code after recursive call
public static void doStuff(int n)
{ doStuff(6)
if(n >= 0)
{
doStuff(n – 2);
System.out.println(n);
}
}
output
0
2
4 SOP(6)
6