CS 46B - Lecture 7

Cover page image

Pre-class reading

Homework Tips

Triangle Numbers

Outline of Triangle Class

public class Triangle 
{ 
   private int width;  
   public Triangle(int aWidth) 
   { 
      width = aWidth; 
   } 
   public int getArea() 
   { 
      . . . 
   } 
}

Handling Triangle of Width 1

Handling the General Case

Completed getArea Method

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

Recursion

Other Ways to Compute Triangle Numbers

Lecture 7 Clicker Question 1

public class MysteryShape
{
   private int size;
   public MysteryShape(int size) { this.size = size; }
   public int getArea()
   {
      if (size == 1) return 1;
      MysteryShape smallerShape = new MysteryShape(size / 2);
      int area = 4 * smallerShape.getArea();
      if (size % 2 == 1) area += 2 * size - 1;
      return area;
   }
}

What is new MysteryShape(4).getArea()?

  1. 1
  2. 4
  3. 16
  4. Something else

Lecture 7 Clicker Question 2

What does this recursive method return?

public static int mystery(int n)
{
   if (n % 2 == 0) // it's even
      return mystery(n / 2);
   else if (n > 1)
      return mystery(3 * n + 1);
   else
      return 1;
}
  1. It always returns 1
  2. It either returns 1 or fails to return
  3. It can return any integer value
  4. It never returns any value

Lecture 7 Clicker Question 3

It is conjectured that the function from the preceding slide always returns, but nobody knows for sure. Some values take quite a few recursive calls:

27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1

Complete this program to return the number of steps until you reach 1. (Each step is either dividing by two, or multiplying by 3 and adding 1.)

What is the result of calling steps(63728127)?

  1. 949
  2. 950
  3. 1132
  4. Something else

Thinking Recursively

Implement isPalindrome Method

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() 
   { 
      . . . 
   } 
}

Thinking Recursively: Step-by-Step

1. Consider various ways to simplify inputs
Here are several possibilities:

Thinking Recursively: Step-by-Step

2. Combine solutions with simpler inputs into a solution of the original problem

Thinking Recursively: Step-by-Step

3. Find solutions to the simplest inputs

Thinking Recursively: Step-by-Step

public boolean isPalindrome() 
{ 
   int length = text.length(); 
   // Separate case for shortest strings. 
   if (length <= 1) { return true; } 
   // Get first and last characters, converted to lowercase. 
   char first = Character.toLowerCase(text.charAt(0)); 
   char last = Character.toLowerCase(text.charAt(length - 1)); 
   if (Character.isLetter(first) && Character.isLetter(last)) 
   { 
      // Both are letters. 
      if (first == last) 
      { 
         // Remove both first and last character. 
         Sentence shorter = new Sentence(text.substring(1, length - 1)); 
         return shorter.isPalindrome(); 
      } 
      else 
      { 
         return false;
      } 
   } 
   else if (!Character.isLetter(last)) 
   { 
      // Remove last character. 
      Sentence shorter = new Sentence(text.substring(0, length - 1)); 
      return shorter.isPalindrome(); 
   } 
   else 
   { 
      // Remove first character. 
      Sentence shorter = new Sentence(text.substring(1)); 
      return shorter.isPalindrome(); 
   } 
}

Lecture 7 Clicker Question 2

Suppose we changed

if (length <= 1) { return true; } 

to

if (length <= 0) { return true; } 

What would be the effect of this change?

  1. The method would work continue to work correctly for all inputs
  2. The method would give the wrong answer for all inputs
  3. The method would throw an exception for some inputs
  4. The method would fall into an infinite recursion for some inputs

Recursive Helper Methods

Recursive Helper Methods

Recursive Helper Methods: isPalindrome

public boolean isPalindrome(int start, int end)
{
   // Separate case for substrings of length 0 and 1.
   if (start >= end) { return true; }
   // Get first and last characters, 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 the last character. 
      return isPalindrome(start, end - 1); 
   } 
   else 
   { 
      // Test substring that doesn't contain the first character. 
      return isPalindrome(start + 1, end); 
   } 
}

Lecture 7 Clicker Question 3

Consider this recursive function:

public static int mystery(int[] values, int start, int value)
{
   if (start == values.length) return value; 
   else return mystery(values, start + 1, Math.max(value, values[start]));
}

What does mystery(new int[] { 3, 1, 4 }, 0, Integer.MIN_VALUE ) return?

  1. 3
  2. 1
  3. 4
  4. Integer.MIN_VALUE