200 likes | 365 Views
CHAPTER GOALS To learn about the method of recursion To understand the relationship between recursion and iteration To analysis problems that are much easier to solve by recursion than by iteration To learn to think recursively To be able to use recursive helper methods
E N D
CHAPTER GOALS • To learn about the method of recursion • To understand the relationship between recursion and iteration • To analysis problems that are much easier to solve by recursion than by iteration • To learn to think recursively • To be able to use recursive helper methods • To understand when the use of recursion affects the efficiency of an algorithm CHAPTER 17RECURSION
Triangle Numbers • Compute the area of a triangle of width n • Assume each [] square has an area of 1 • Also called the nth triangle number • Example --The third triangle number is 6 [] [] [] [] [] [] • Outline of Triangle Class public class Triangle { public Triangle(int aWidth) { width = aWidth; } public int getArea() { ... } private int width; }
Handling Triangle • Base case: Width 1 • The triangle consists of a single square -- area is 1 • Add the code to getArea method for width 1 public int getArea() { if (width == 1) return 1; } • General case: • Assume we know the area of the smaller, colored triangle • Area of larger triangle can be calculated as:smallerArea + width • To get the area of the smaller triangle • make a smaller triangle and ask it for its areaTriangle smallerTriangle = new Triangle(width - 1); int smallerArea = smallerTriangle.getArea(); [] [] [][] [] [][] [] [] []
Completed getArea method • That method makes a smaller triangle of width 2 • It calls getArea on that triangle • That method makes a smaller triangle of width 1 • It calls getArea on that triangle • That method returns 1 • The method returns smallerArea + width = 1 + 2 = 3 • The method returns smallerArea + width = 3 + 3 = 6 • The method returns smallerArea + width = 6 + 4 = 10 • The code public int getArea() { if (width == 1) return 1; Triangle smallerTriangle = new Triangle(width - 1); int smallerArea = smallerTriangle.getArea(); return smallerArea + width; } • Computing the area of a triangle with width 4 • getArea method makes a smaller triangle of width 3 • It calls getArea on that triangle
Recursion • A recursive computation solves a problem by using the solutionof the same problem with simpler input • For recursion to terminate, there must be special cases for the simplest inputs. • To complete our Triangle example, we must handle width <= 0 • Add this line to the getArea method if (width <= 0) return 0;
File Triangle.java 18: 19: /** 20: Computes the area of the triangle. 21: @return the area 22: */ 23: public int getArea() 24: { 25: if (width <= 0) return 0; 26: if (width == 1) return 1; 27: Triangle smallerTriangle = new Triangle(width - 1); 28: int smallerArea = smallerTriangle.getArea(); 29: return smallerArea + width; 30: } 31: 32: private int width; 33: } 01: /** 02: A triangular shape composed of stacked unit squares like this: 03: [] 04: [][] 05: [][][] 06: . . . 07: */ 08: public class Triangle 09: { 10: /** 11: Constructs a triangular shape 12: @param aWidth the width (and height) of the triangle 13: */ 14: public Triangle(int aWidth) 15: { 16: width = aWidth; 17: }
TriangleTest.java 01: import javax.swing.JOptionPane; 02: 03: public class TriangleTest 04: { 05: public static void main(String[] args) 06: { 07: String input = JOptionPane.showInputDialog("Enter width"); 08: int width = Integer.parseInt(input); 09: Triangle t = new Triangle(width); 10: int area = t.getArea(); 11: System.out.println("Area = " + area); 12: } 13: }
Permutations of a String • Design a class that lists all permutations of a string • A permutation is a rearrangement of the letters • The string "eat" has six permutations:“eat”, “eta”, “aet”, “aet”, “tea”, “tae” • Public Interface of PermutationGenerator class PermutationGenerator { public PermutationGenerator(String s) { . . . } public String nextPermutation() {. . . } public boolean hasMorePermutations() { . . . } }
File PermutationGeneratorTest.java 01: /** 02: This program tests the permutation generator. 03: */ 04: public class PermutationGeneratorTest 05: { 06: public static void main(String[] args) 07: { 08: PermutationGenerator generator 09: = new PermutationGenerator("eat"); 10: while (generator.hasMorePermutations()) 11: System.out.println(generator.nextPermutation()); 12: } 13: }
To Generate All Permutations • Generate all permutations that start with 'e' , then 'a' then 't' • To generate permutations starting with 'e', we need to find all permutations of "at" • This is the same problem with simpler inputs. • Use recursion • nextPermutaion method returns one permutation at a time • PermutationGenerator remembers its state • The string we are permuting (word) • Position of the current character (current) • PermutationGenerator of the substring (tailGenerator) • nextPermutation asks tailGenerator for its next permutation and returnsword.charAt(current) + tailGenerator.nextPermutation();
Handling the Special Case • When the tail generator runs out of permutations, we need to: • Increment the current position • Compute the tail string that contains all letters except for the current one • Make a new permutation generator for the tail string
File PermutationGenerator.java 01: /** This class generates permutations of a word. 03: */ 04: class PermutationGenerator 05: { 06: /** Constructs a permutation generator. 08: @param aWord the word to permute 09: */ 10: public PermutationGenerator(String aWord) 11: { 12: word = aWord; 13: current = 0; 14: if (word.length() > 1) 15: tailGenerator = new PermutationGenerator(word.substring(1)); 16: System.out.println("Generating " + word ); 17: } 19: /** 20: Computes the next permutation of the word. 21: @return the next permutation 22: */ 23: public String nextPermutation() 24: {
25: if (word.length() == 1) 26: { current++; return word; } 31: String r = word.charAt(current) + tailGenerator.nextPermutation(); 33: if (!tailGenerator.hasMorePermutations()) 34: { 35: current++; 36: if (current < word.length()) 37: { 38: String tailString = word.substring(0, current) 39: + word.substring(current + 1); 40: tailGenerator = new PermutationGenerator(tailString); 41: } 42: } 44: return r; 45: } 47: /** Tests whether there are more permutations. 49: @return true if more permutations are available 50: */ 51: public boolean hasMorePermutations() 52: { return current < word.length();} 56: private String word; 57: private int current; 58: private PermutationGenerator tailGenerator; 59: }
Recursive Helper Method • The public boolean method isPalindronecalls helper method isPalindrome(int start, int end) • Helper method skips over matching letter pairs and non-letters and calls itself recursively
Recursive Helper Method public boolean isPalindrome(int start int end) { //separate case for substrings of length 0 or 1 if (start>=end) return true; //get first and last character, converted to lowercase char first = Character.toLowerCase(text.charAt(start)); char last = Character.toLowerCase(text.charAt(end)); if ((Character.isLetter(first) && Character.isLetter(last)) { if (first == last) { //test substring that doesn't contain the matching letters return isPalindrome(start +1, end -1); } else return false; } else if (!Character.isLetter(last)) { //test substring that doesn't contain last character return isPalindrome(start, end -1); } else { //test substring that doesn't contain first character return isPalindrome(start + 1, end); }
Fibonacci Sequence • Fibonacci sequence is a sequence of numbers defined byf1 = 1, f2 = 1fn = fn-1 + fn-2 • First ten terms 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 • The Efficiency of Recursion • You can generate the Fibonacci series using either recursion or iteration • Both are conceptually easy to understand and program • Iterative solution is much faster • Palindrome test can be implemented as either recursion or iteration • Both are easy to program • Both run about the same speed • Permutation generator can be solved using either recursion or iteration • Recursive solution is dramatically easier to understand and implement • Both run at about the same speed
File FibTest.java 18: } 19: System.exit(0); 20: } 21: 22: /** 23: Computes a Fibonacci number. 24: @param n an integer 25: @return the nth Fibonacci number 26: */ 27: public static int fib(int n) 28: { 29: if (n <= 2) return 1; 30: else return fib(n - 1) + fib(n - 2); 31: } 32: } 01: import javax.swing.JOptionPane; 02: 03: /** 04: This program computes Fibonacci numbers using a recursive 05: method. 06: */ 07: public class FibTest 08: { 09: public static void main(String[] args) 10: { 11: String input = JOptionPane.showInputDialog("Enter n: "); 12: int n = Integer.parseInt(input); 13: 14: for (int i = 1; i <= n; i++) 15: { 16: int f = fib(i); 17: System.out.println("fib(" + i + ") = " + f);
File FibTrace.java 20: /** 21: Computes a Fibonacci number. 22: @param n an integer 23: @return the nth Fibonacci number 24: */ 25: public static int fib(int n) 26: { 27: System.out.println("Entering fib: n = " + n); 28: int f; 29: if (n <= 2) f = 1; 30: else f = fib(n - 1) + fib(n - 2); 31: System.out.println("Exiting fib: n = " + n 32: + " return value = " + f); 33: return f; 34: } 35: } 01: import javax.swing.JOptionPane; 03: /** This program prints trace messages that show how often the 05: recursive method for computing Fibonacci numbers calls itself. 06: */ 07: public class FibTrace 08: { 09: public static void main(String[] args) 10: { 11: String input = JOptionPane.showInputDialog("Enter n: "); 12: int n = Integer.parseInt(input); 14: int f = fib(n); 16: System.out.println("fib(" + n + ") = " + f); 17: System.exit(0); 18: }
19: System.exit(0); 20: } 21: 22: /** 23: Computes a Fibonacci number. 24: @param n an integer 25: @return the nth Fibonacci number 26: */ 27: public static double fib(int n) 28: { 29: if (n <= 2) return 1; 30: double fold = 1; 31: double fold2 = 1; 32: double fnew = 1; 33: for (int i = 3; i <= n; i++) 34: { 35: fnew = fold + fold2; 36: fold2 = fold; 37: fold = fnew; 38: } 39: return fnew; 40: } 41: } File FibLoop.java 01: import javax.swing.JOptionPane; 03: /** 04: This program computes Fibonacci numbers using an iterative 05: method. 06: */ 07: public class FibLoop 08: { 09: public static void main(String[] args) 10: { 11: String input = JOptionPane.showInputDialog("Enter n: "); 12: int n = Integer.parseInt(input); 13: 14: for (int i = 1; i <= n; i++) 15: { 16: double f = fib(i); 17: System.out.println("fib(" + i + ") = " + f); 18: }