Transcript Slide 1

Chapter 13 - Recursion
Copyright © 2014 by John Wiley & Sons. All rights reserved.
1
Chapter Goals
 To learn to “think recursively”
 To be able to use recursive helper methods
 To understand the relationship between recursion and
iteration
 To understand when the use of recursion affects the
efficiency of an algorithm
 To analyze problems that are much easier to solve by
recursion than by iteration
 To process data with recursive structures using mutual
recursion
Copyright © 2014 by John Wiley & Sons. All rights reserved.
2
Recursion
 For some problems, it’s useful to have a method call
itself.
 A method that does so is known as a recursive
method.
 A recursive method can call itself either directly or
indirectly through another method.
 E.g.
•
•
•
•
•
•
•
Fibonacci method
Factorial method
Towers of Hanoi
Merge sort
Linear search
Binary search
Quick sort
Copyright © 2014 by John Wiley & Sons. All rights reserved.
3
Recursion
 A recursive method always contain a base case(s):
• The simplest case that method can solve.
• If the method is called with a base case, it returns a result.
 If the method is called with a more complex
problem, it breaks problem into same but simpler
sub-problems and recursively call itself on these
smaller sub-problems.
 The recursion step normally includes a return
statement which allow the method to combine result
of smaller problems to get the answer and pass
result back to its caller.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
4
Recursion
 For the recursion to eventually terminate, each time
the method calls itself with a simpler version of the
original problem, the sequence of smaller and smaller
problems must converge on a base case.
 When the method recognizes the base case, it
returns a result to the previous copy of the method.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
5
Factorial
 Example Using Recursion: Factorial
• factorial of a positive integer n , called n!
n! = n · (n – 1) · (n – 2) · … · 1
• 1! =1
• 0! =1
• E.g. 5! = 5.4.3.2.1 = 120
Copyright © 2014 by John Wiley & Sons. All rights reserved.
6
Programming Question
 Write a iterative (non-recursive) method factorialIterrative in class
FactorialCalculator to calculate factorial of input parameter n.
 Call this in the main method to print factorials of 0 through 50
 A sample output is below:
Copyright © 2014 by John Wiley & Sons. All rights reserved.
7
Answer:
 Try setting n=100 in main. How does the output
change?
 How does the output change when data type is int?
public class FactorialCalculator
{
public static long factorialIterative(long n)
{
long factorial = n;
for(int i=(int)n;i>=1;i--)
factorial *= i;
return factorial;
}
public static void main(String args[])
{
for(int n=0;n<=100;n++)
System.out.println(n+"!= "+factorialIterative(n));
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
8
• How to write it recursively?
• Recursive aspect comes from : n! = n.(n-1)!
• E.g. 5!
Copyright © 2014 by John Wiley & Sons. All rights reserved.
9
Programming Question
 Modify FactorialCalculator to add a recursive factorial
method.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
10
Answer
• Recursive method:
public static long factorial(long number)
{
if (number ==1 || number==0) //Base Case
{
return number;
}
else //Recursion Step
{
return number * factorial(number-1);
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
11
public class FactorialCalculator
{
public static long factorialIterative(int n)
{
int factorial = n;
for(int i=(int)n;i>=1;i--)
factorial *= i;
return factorial;
}
public static long factorialRecursive(long number)
{
if (number ==1 || number==0) //Base Case
{
return number;
}
else //Recursion Step
{
return number * factorialRecursive(number-1);
}
}
public static void main(String args[])
{
for(int n=0;n<=100;n++)
System.out.println(n+"!= "+factorialRecursive(n));
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
12
Programming Question
 Since factorial values tend to be large, using BigInteger
rather than long as data type is more appropriate.
 Modify FactorialCalculator to use BigInteger data type
rather than long (modify recursive version only).
Copyright © 2014 by John Wiley & Sons. All rights reserved.
13
 Since factorial values tend to be large, using BigInteger
rather than long as data type is more appropriate:
import java.math.BigInteger;
public class FactorialCalculator
{
public static BigInteger factorialRecursive(BigInteger number)
{
if (number.compareTo(BigInteger.ONE)==0 || number.compareTo(BigInteger.ZERO)==0) //Base Case
{
return number;
}
else //Recursion Step
{
return number.multiply(factorialRecursive(number.subtract(BigInteger.ONE)));
}
}
public static void main(String args[])
{
for(int n=0;n<=100;n++)
System.out.println(n+"!= "+factorialRecursive(BigInteger.valueOf(n)));
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
14
 Output:
Copyright © 2014 by John Wiley & Sons. All rights reserved.
15
Programming Question
 Using recursion: Fibonacci Series
• The Fibonacci series: 0, 1, 1, 2, 3, 5, 8, 13, 21, …
• Begins with 0 and 1
• Each subsequent Fibonacci number is the sum of the previous
two.
 Implement the tester class FinbonacciCalculator that
contains the recursive method fibonacci.
• Hint: Use BigInteger as return data type
• Call this method in main method to print fibonacci values of 0
to 40:
Copyright © 2014 by John Wiley & Sons. All rights reserved.
16
 E.g. fibonacci(3)
Copyright © 2014 by John Wiley & Sons. All rights reserved.
17
 A sample run is shown:
Copyright © 2014 by John Wiley & Sons. All rights reserved.
18
Answer
FibonacciCalculator.java
Copyright © 2014 by John Wiley & Sons. All rights reserved.
19
Java Stack and Heap
 Before we look at how recursive methods are stored and
processed, lets look at two important concept in java:
• Java stack and heap
 Stack:
• A memory space reserved for your process by the OS
• the stack size is limited and is fixed and it is determined in the
compiler phase based on variables declaration and other compiler
options
• Mostly, the stack is used to store methods variables
• Each method has its own stack (a zone in the process stack),
including main, which is also a function.
• A method stack exists only during the lifetime of that method
Copyright © 2014 by John Wiley & Sons. All rights reserved.
20
Java Stack and Heap
 Heap:
• A memory space managed by the OS
• the role of this memory is to provide additional memory
resources to processes that need that supplementary space at
run-time (for example, you have a simple Java application that
is constructing an array with values from console);
• the space needed at run-time by a process is determined by
functions like new (remember, it the same function used to
create objects in Java) which are used to get additional space
in Heap.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
21
Recursion and the Method-Call Stack
 Let’s begin by returning to the Fibonacci example
• Method calls made within fibonacci(3):
• Method calls in program execution stack:
Method stays
in stack as
long has not
completed
and returned
Copyright © 2014 by John Wiley & Sons. All rights reserved.
22
Programming Question
Write a class Sentence that define the recursive method
isPalindrome() that check whether a sentence is a
palindrome or not.
 Palindrome: a string that is equal to itself when you
reverse all characters
• Go hang a salami, I'm a lasagna hog
• Madam, I'm Adam
Copyright © 2014 by John Wiley & Sons. All rights reserved.
23
Class Skeleton is provided for you. Add a main method that
create several sentences and print if they are palindromes.
public class Sentence
{
private String text;
/**
Constructs a sentence.
@param aText a string containing all characters of the sentence
*/
public Sentence(String aText)
{
text = aText;
}
/**
Tests whether this sentence is a palindrome.
@return true if this sentence is a palindrome, false otherwise
*/
public boolean isPalindrome()
{
. . .
}
public static void main(String args[])
{
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
24
Hint:
 Remove both the first and last characters.
 If they are same check if remaining string is a
palindrome.
 What are the base cases/ simplest input?
• Strings with a single character
• They are palindromes
• The empty string
• It is a palindrome
Copyright © 2014 by John Wiley & Sons. All rights reserved.
25
Answer
Sentence.java
1 public class Sentence {
2
3
private String text;
4
5
public Sentence(String aText)
{
6
text = aText;
7
}
8
9
public boolean isPalindrome()
{
10
int length = text.length();
11
12
if (length <= 1) { return true; } //BASE CASE
13
14
char first = Character.toLowerCase(text.charAt(0));
15
char last = Character.toLowerCase(text.charAt(length - 1));
16
17
if (Character.isLetter(first) && Character.isLetter(last))
{
18
if (first == last)
{
19
Sentence shorter = new Sentence(text.substring(1, length - 1));
20
return shorter.isPalindrome();
21
}
22
else
{
23
return false;
24
}
25
}
26
else if (!Character.isLetter(last))
{
27
Sentence shorter = new Sentence(text.substring(0, length - 1));
28
return shorter.isPalindrome();
29
}
30
else
{
31
Sentence shorter = new Sentence(text.substring(1));
32
return shorter.isPalindrome();
33
}
34
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
Continued..
26
Answer
36
37
38
39
40
41
42
43
44
45
46}
public static void main(String[] args)
{
Sentence p1 = new Sentence("Madam, I'm Adam.");
System.out.println(p1.isPalindrome());
Sentence p2 = new Sentence("Nope!");
System.out.println(p2.isPalindrome());
Sentence p3 = new Sentence("dad");
System.out.println(p3.isPalindrome());
Sentence p4 = new Sentence("Go hang a salami, I'm a lasagna hog.");
System.out.println(p4.isPalindrome());
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
27
Recursion Vs Iteraion
 Recursion has many negatives.
• It repeatedly invokes the mechanism, and consequently the
overhead, of method calls.
• This repetition can be expensive in terms of both processor
time and memory space.
• Each recursive call causes another copy of the method to be
created
• this set of copies can consume considerable memory space.
• Since iteration occurs within a method, repeated method calls
and extra memory assignment are avoided.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
28
Question
You can compute the factorial function either with a loop,
using the definition that n! = 1 × 2 × . . . × n, or recursively,
using the definition that 0! = 1and
n! = (n – 1)! × n. Is the recursive approach inefficient in this
case?
Answer: No, the recursive solution is about as
efficient as the iterative approach. Both require n –
1 multiplications to compute n!.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
29
Question
To compute the sum of the values in an array, you can
split the array in the middle, recursively compute the
sums of the halves, and add the results. Compare the
performance of this algorithm with that of a loop that
adds the values.
Answer: The recursive algorithm performs about as
well as the loop. Unlike the recursive Fibonacci
algorithm, this algorithm doesn’t call itself again on
the same input. For example, the sum of the array 1
4 9 16 25 36 49 64 is computed as the sum of 1 4 9
16 and 25 36 49 64, then as the sums of 1 4, 9 16,
25 36, and 49 64, which can be computed directly.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
30
Programming Question
 Permutations
 Using recursion, you can find all arrangements of a set of
objects.
 A permutation is a rearrangement of the letters.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
31
Programming Question
 E.g. Permutations
• The string "eat" has six permutations:
"eat"
"eta"
"aet"
"ate"
"tea"
"tae”
Design a class Permutations that contains a recursive
method permutations that takes a string and return a
list of permutations
public static ArrayList<String> permutations(String word)
In main method call this method to print all
permutations possible.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
32
 Problem: Generate all the permutations of "eat".
• First generate all permutations that start with the letter 'e', then
'a' then 't'.
 How do we generate the permutations that start with
'e'?
• We need to know the permutations of the substring "at".
• But that’s the same problem—to generate all permutations— with
a simpler input
• Prepend the letter 'e' to all the permutations you found of 'at'.
• Do the same for 'a' and 't'.
 Provide a special case for the simplest strings.
• The simplest string is the empty string, which has a single
permutation—itself.
Copyright © 2014 by John Wiley & Sons. All rights reserved.
33
Answer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.ArrayList;
Permutations.java
/**
This program computes permutations of a string.
*/
public class Permutations
{
public static void main(String[] args)
{
for (String s : permutations("eat"))
{
System.out.println(s);
}
}
/**
Gets all permutations of a given word.
@param word the string to permute
@return a list of all permutations
*/
public static ArrayList<String> permutations(String word)
{
ArrayList<String> result = new ArrayList<String>();
Copyright © 2014 by John Wiley & Sons. All rights reserved.
Continued
34
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// The empty string has a single permutation: itself
if (word.length() == 0)
{
result.add(word);
return result;
}
else
{
// Loop through all character positions
for (int i = 0; i < word.length(); i++)
{
// Form a shorter word by removing the ith character
String shorter = word.substring(0, i) + word.substring(i + 1);
// Generate all permutations of the simpler word
ArrayList<String> shorterPermutations = permutations(shorter);
// Add the removed character to the front of
// each permutation of the simpler word,
for (String s : shorterPermutations)
{
result.add(word.charAt(i) + s);
}
}
// Return all permutations
return result;
}
}
}
Copyright © 2014 by John Wiley & Sons. All rights reserved.
Continued
35
Program Run:
eat
eta
aet
ate
tea
tae
Copyright © 2014 by John Wiley & Sons. All rights reserved.
36
References
 Java How to Program, Dietel and Dietel
 http://www.itcsolutions.eu/2011/02/06/tutorial-java8-understand-stack-and-heap/
Copyright © 2014 by John Wiley & Sons. All rights reserved.
37