AP Computer Science Chapter 8 (MC)
20) Merging two lists of n sorted elements would take O(n2) time.
False Explanation: 2n elements would need to be examined and this is O(n).
19) The pivot value selected in a quick sort should be the smallest element in the list.
False Explanation: Choosing the smallest element causes the list to be divided unevenly. The best choice would be to choose the middle element, but often an element is chosen randomly because that takes less time.
21) Infinite recursion is impossible as long as you have a base case.
False Explanation: If the recursive case is such that the base case will never be reached, then you have infinite recursion. For example: int bar(int n) { if (n < 0) return 0; else return bar(n); }
24) A recursive method that doesn't return anything with result in infinite recursion.
False Explanation: It is possible to have a void recursive method. (For example maybe it prints something rather than returning anything.)
3) Traversing a maze is much easier to do iteratively than recursively.
False Explanation: One reason that recursion is appealing is that it automatically backtracks to the point of the last decision. In traversing a maze, when one reaches a dead end, the best place to continue is at the point of the previous intersection (or decision). So, backtracking is performed. To solve a maze iteratively requires implementing a backtracking mechanisms, which is available automatically in recursion.
13) A recursive algorithm is superior to an iterative algorithm because it is computationally more efficient.
False Explanation: Recursion is more inefficient than iteration.
7) The recursive method to solve the Towers of Hanoi is usable only if the parameter for the number of disks is 7 or smaller.
False Explanation: The Towers of Hanoi solution can be used for any sized disk as long as it is at least 1.
11) Assume the method below is called initially with i = 0 public int question(String a, char b, int i) { if (i = = a.length( )) return 0; else if (b = = a.charAt(i)) return question(a, b, i+1) + 1; else return question(a, b, i+1); } The method returns 1 if char b appears in String a at least once, and 0 otherwise.
False Explanation: The method compares each character in String a with char b until i reaches the length of String a. 1 is added to the return value for each match. So the method returns the number of times char b appears in String a.
6) Consider the following recursive sum method: public int sum(int x) { if(x = = 0) return 0; else return sum(x - 1) + 1; }
False Explanation: The original method causes infinite recursion if called with a parameter < 0, but works properly if called with any parameter >= 0. With the new base case, the method now works properly if called with any parameter >= 1 but causes infinite recursion if the parameter < 1. So, sum(0) now differs from what it had previously.
10) We can define a list of int values recursively as: a list_item, followed by a comma, followed by a list where a list_item is any int value.
False Explanation: The recursive definition does not include a base case so that all lists of int values will be infinitely long!
9) Since iterative solutions often use loop variables and recursive solutions do not, the recursive solution is usually more memory efficient (uses less memory) than the equivalent iterative solution.
False Explanation: The recursive solution may use no local variables whatsoever, but the recursive solution usually uses parameters. Every time the method is called recursively, new parameters are required, and so recursively solutions usually use a substantially larger amount of memory than an iterative solution (it depends on how many times the method is called recursively).
25) If method f1 calls method f2 calls method f3, we have indirect recursion.
False Explanation: There is no recursion in that. Indirect recursion would be f1 calling f2 calling f1 again (and so on).
23) When a method is called by itself, it the second invocation uses the same storage space for local variables, so in effect the invocation share the variables.
False Explanation: When a method is called recursively new local variables are created.
2) The following method lacks a base case. public int noBaseCase(int x) { if(x > 0) return noBaseCase(x - 1) + 1; else return noBaseCase(x - 2) + 2; }
True Explanation: A base case is a condition that, when taken, stops the recursion by not calling the method recursively. In the above method, there is a condition, but whether the condition is true or false, the method invokes itself recursively.
17) Recursion can be used when sorting an array of elements.
True Explanation: Both merge sort and quick sort are often implemented recursively.
15) Aside from writing recursive methods, another way that recursion is often used is to define mathematical functions.
True Explanation: Mathematics often defines functions recursively for simplicity.
16) Merge sort and quick sort are more time efficient than insertion sort and selection sort.
True Explanation: Merge sort has time efficiency O(nlogn) and quick sort, while it's worst case efficiency is O(n2) has average O(nlogn). O(nlogn) is more efficient than O(n2) which is what insertion and selection sort are.
4) Some problems are easier to solve recursively than iteratively.
True Explanation: Since recursion performs backtracking automatically, any problem that requires backtracking is easier to solve using recursion. Such problems include traversing a maze and searching through a "search space", a topic covered in Artificial Intelligence and Advanced Algorithms courses. In some cases, it is easy to find a recursive solution and so the recursive solution is easier than the iterative solution.
8) A Koch snowflake of order = 1 can be drawn without recursion.
True Explanation: The Koch snowflake of order 1 is made up of straight lines. It is not until the order is greater than 1 that recursion is applied.
5) The following two methods will both compute the same thing when invoked with the same value of x. That is, method1(x) = = method2(x). public int method1(int x) { if(x > 0) return method1(x - 1) + 1; else return 0; } public int method2(int x) { if(x > 0) return 1 + method2(x - 1); else return 0; }
True Explanation: The only difference between the two methods is the order of the recursive call and adding 1 to the return value. The difference is denoted by calling the first method head recursive and the second tail recursive. So both methods will compute the same value, but arrive at the value in different ways.
18) A recursive sort typically divides the list into smaller sublists which are sorted recursively.
True Explanation: The sublists are then combined.
14) The method below computes the value of x % y (x mod y) recursively, assuming that x and y not negative numbers. public int recursiveMod(int x, int y) { if (x < y) return x; else return recursiveMod(x - y, y); }
True Explanation: The value x % y can be computed by continually subtracting y from x until x < y. Then, the result is x. For instance, 7 % 3 = 4 % 3 = 1 % 3 = 1.
12) The recursive method below would execute approximately log 2 n times for an initial parameter n. public void logcode(int n) { if (n > 1) logcode(n / 2); }
True Explanation: This method recursively calls itself with n being half its original value. If n starts at 16, the second call has n = 8, the third has n = 4, the fourth has n = 2, the fifth and final call has n = 1. If n starts at 32, it adds one additional call. If we double n again, it only adds 1 more recursive call. This is a log 2 n behavior.
22) Infinite recursion can occur with indirect recursion.
True Explanation: Two or more methods could call each other inifintely.
1) A recursive method without a base case leads to infinite recursion.
True Explanation: Without the base case, the recursive method calls itself without the ability to stop, and thus leads to infinite recursion.
The following method recognizes whether a String parameter consists of a specific pattern and returns true if the String has that pattern, false otherwise. Use this recursive method to answer questions 23 - 25. public boolean patternRecognizer(String a) { if(a == null) return false; else if (a.length( ) = = 1 | | (a.length( ) = = 2 && a.charAt(0) = = a.charAt(1) ) ) return true; else if (a.length( ) = = 2 && a.charAt(0) != a.charAt(1) ) return false; else if (a.charAt(0) == a.charAt(a.length( ) - 1)) return patternRecognizer(a.substring(1, a.length( ) - 1)); else return false; } 24) If the method is called as patternRecognizer(x) where x is "aa", what will the result be? a) true b) false c) a NullPointerException d) a run-time error e) infinite recursion
a Explanation: One of the base cases tests to see if the String has 2 characters and if so, returns true if the two characters are the same.
For questions 9 - 13, assume that int[ ] a = {6, 2, 4, 6, 2, 1, 6, 2, 5} and consider the two recursive methods below foo and bar. public int foo(int[ ] a, int b, int j) { if (j < a.length) if (a[j] != b) return foo (a, b, j+1); else return foo (a, b, j+1) + 1; else return 0; } public int bar(int[ ] a, int j) { if (j < a.length) return a[I] + bar(a, j+1); else return 0; } 11) What is the result of calling foo(a, 2, 9);? a) 0 b) 1 c) 2 d) 3 e) 4
a Explanation: The method foo counts the number of occurrences of the int parameter in the second position in the array starting at the index given as the third parameter. So, foo(a, 2, 9) results in the base case being executed immediately because 9 = = a.length and the base case returns 0.
For questions 9 - 13, assume that int[ ] a = {6, 2, 4, 6, 2, 1, 6, 2, 5} and consider the two recursive methods below foo and bar. public int foo(int[ ] a, int b, int j) { if (j < a.length) if (a[j] != b) return foo (a, b, j+1); else return foo (a, b, j+1) + 1; else return 0; } public int bar(int[ ] a, int j) { if (j < a.length) return a[I] + bar(a, j+1); else return 0; } 10) What is the result of calling foo(a, 3, 0);? a) 0 b) 1 c) 2 d) 3 e) 4
a Explanation: The method foo counts the number of occurrences of the int parameter in the second position in the array starting at the index given as the third parameter. So, foo(a, 3, 0) finds the number of 3s in a. There are none.
For questions 9 - 13, assume that int[ ] a = {6, 2, 4, 6, 2, 1, 6, 2, 5} and consider the two recursive methods below foo and bar. public int foo(int[ ] a, int b, int j) { if (j < a.length) if (a[j] != b) return foo (a, b, j+1); else return foo (a, b, j+1) + 1; else return 0; } public int bar(int[ ] a, int j) { if (j < a.length) return a[I] + bar(a, j+1); else return 0; } 9) What is the result of calling foo(a, 2, 0);? a) 0 b) 1 c) 2 d) 3 e) 4
a Explanation: The method foo counts the number of occurrences of the int parameter in the second position in the array starting at the index given as the third parameter. So, foo(a, 3, 0) finds the number of 3s in a. There are none.
The following method recognizes whether a String parameter consists of a specific pattern and returns true if the String has that pattern, false otherwise. Use this recursive method to answer questions 23 - 25. public boolean patternRecognizer(String a) { if(a == null) return false; else if (a.length( ) = = 1 | | (a.length( ) = = 2 && a.charAt(0) = = a.charAt(1) ) ) return true; else if (a.length( ) = = 2 && a.charAt(0) != a.charAt(1) ) return false; else if (a.charAt(0) == a.charAt(a.length( ) - 1)) return patternRecognizer(a.substring(1, a.length( ) - 1)); else return false; } 23) Which String below would result in patternRecognizer returning true? a) "abcba" b) "aaabbb" c) "abcde" d) "aabba" e) all of the above Strings will result in the method returning true
a Explanation: The method patternRecognizer returns true if the String is a palindrome. This can be seen by analyzing the code. If the String has 1 character, or 2 characters which are equal, it returns true, otherwise if the first and last characters are the same, it recursively calls itself with the substring starting at character 1 and going to the second to last character (so, since in "abcba" the first and last characters are the same, the method is called recursively with the substring "bcb"). Only if the first and last characters do not match is false returned. The only palindrome in the list of options is a, "abcba".
For questions 9 - 13, assume that int[ ] a = {6, 2, 4, 6, 2, 1, 6, 2, 5} and consider the two recursive methods below foo and bar. public int foo(int[ ] a, int b, int j) { if (j < a.length) if (a[j] != b) return foo (a, b, j+1); else return foo (a, b, j+1) + 1; else return 0; } public int bar(int[ ] a, int j) { if (j < a.length) return a[I] + bar(a, j+1); else return 0; } 13) What is the result of bar(a, 8);? a) 0 b) 5 c) 6 d) 12 e) 34
b Explanation: The bar method recursively sums the elements of array a starting at the location of the second parameter (8 in this case). So, bar(a, 8) sums up only the last element in the array, 5, and so 5 is returned.
14) What does the following recursive method determine? public boolean question16(int[ ]a, int[ ] b, int j) { if(j = = a.length) return false; else if (j = = b.length) return true; else return question16(a, b, j+1); } a) Returns true if a and b are equal in size, false otherwise b) Returns true if a is larger than b, false otherwise c) Returns true if b is larger than a, false otherwise d) Returns true if a and b have no elements e) Returns the length of array a + length of array b
b Explanation: The method returns true if the third parameter, j, is equal to the length of b but not equal to the length of a. Thus, the method returns true if the third parameter has reached the value indicating the end of array b but not the end of array a so this is true if a is larger than b. If a and b are equal length or if a is shorter than b, false is returned.
For questions 4 - 7, refer to the following recursive factorial method. public int factorial(int x) { if (x > 1) return x * factorial (x - 1); else return 1; } 5) What is returned if factorial(0) is called? a) 0 b) 1 c) 2 d) nothing, factorial(0) causes infinite recursion e) nothing, factorial(0) produces a run-time error
b Explanation: With factorial(0), (x > 1) is not true, so the base case is executed and 1 is returned. Therefore, even though ordinarily 0 * value = 0, the factorial(0) is computed as 1.
For questions 19 - 21, consider the following representation of grid and the maze code from Chapter 8. Grid: 11111100 00100100 00100110 00110010 00011000 00001111 Code: public boolean traverse(int row, int column) { if (valid(row, column)) { boolean done = false; grid[row][column] = TRIED; if (row == grid.length - 1 && column == grid[0].length - 1) done = true; else { done = traverse(row + 1, column); if(!done) done = traverse(row, column + 1); if(!done) done = traverse(row - 1, column); if(!done) done = traverse(row, column - 1); } if(done) grid[row][column] = PATH; } return done; } 19) If traverse is first called with traverse(0, 0); what will the first recursive call of traverse be? a) traverse(0, 0); b) traverse(0, 1); c) traverse(1, 0); d) traverse(1, 1); e) traverse(0, -1);
c Explanation: Since row and grid do not equal the bottom right node in the grid (that is, we haven't found the solution yet), the else clause, done = traverse(row + 1, column);, is executed, resulting in traverse(1, 0); being called.
For questions 1 - 2, use the following recursive method. public int question1_2(int x, int y) { if (x == y) return 0; else return question1_2(x-1, y) + 1; } 1) If the method is called as question1_2(8, 3), what is returned? a) 11 b) 8 c) 5 d) 3 e) 24
c Explanation: The method computes x - y if x > y. The method works as follows: each time the method is called recursively, it subtracts 1 from x until (x == y) is becomes true, and adds 1 to the return value. So, 1 is added each time the method is called, and the method is called once for each int value between x and y.
8) What is wrong with the following recursive sum method? The method is supposed to sum up the values between 1 and x (for instance, sum(5) should be 5 + 4 + 3 + 2 + 1 = 15). public int sum(int x) { if(x = = 0) return 0; else return sum(x - 1) + x; } a) the base case should return 1 instead of 0 b) the recursive case should return sum(x - 1) + 1; instead of sum(x - 1) + x; c) the base case condition should be (x <= 0) instead of (x = = 0) d) the recursive case should return sum(x) + 1; e) the method should return a boolean instead of an int
c Explanation: The method does not appropriately handle a negative parameter, such as sum(-5). The result is infinite recursion. We might define a negative parameter as something that should return 0, or allow a negative parameter to compute a negative sum as in: public int sum(int x) { if(x = = 0) return 0; else if (x < 0) return -1 * sum(-x); else return sum(x - 1) + x; }
For questions 4 - 7, refer to the following recursive factorial method. public int factorial(int x) { if (x > 1) return x * factorial (x - 1); else return 1; } 6) How many times is the factorial method invoked if originally called with factorial(5)? Include the original method call in your counting. a) 1 b) 4 c) 5 d) 6 e) 7
c Explanation: The method is first invoked with factorial(5), which in turn returns 5 * factorial(4), so factorial is invoked again, which in turn returns 4 * factorial(3), so factorial is invoked again, which in turn returns 3 * factorial(2), so factorial is invoked again, which in turn returns 2 * factorial(1), so factorial is invoked again, and finally factorial(1) invokes the base case and returns 1. So, factorial was invoked 5 times.
3) The following method should return true if the int parameter is even and either positive or 0, and false otherwise. Which set of code should you use to replace ... so that the method works appropriately? public boolean question3(int x) { ... } a) if (x = = 0) return true; else if (x < 0) return false; else return question3(x - 1); b) if (x = = 0) return false; else if (x < 0) return true; else return question3(x - 1); c) if (x = = 0) return true; else if (x < 0) return false; else return question3(x - 2); d) if (x = = 0) return false; else if (x < 0) return true; else return question3(x - 2); e) return(x = = 0);
c Explanation: The method will recursively call itself subtracting 2 from x until x = = 0 or x < 0. If x == 0, then it x-2 * i == 0 (for some int value i) or x == 2 * i ,so x must be even. Otherwise, the recursion ends when x < 0, meaning that the original x was odd or less than 0.
15) Why is the following method one which has infinite recursion? public int infiniteRecursion(int n) { if (n > 0) return infiniteRecursion(n) + 1; else return 0; } a) Because there is no base case b) Because the base case will never be true c) Because the recursive call does not move the parameter closer to the base case d) Because the recursive call moves the problem further away from the base case e) None of the above, there is no infinite recursion in this method
c Explanation: The recursive case has the method calling itself with the same parameter, and so n does not change, thus if (n > 0) is initially true, it will remain true.
For questions 19 - 21, consider the following representation of grid and the maze code from Chapter 8. Grid: 11111100 00100100 00100110 00110010 00011000 00001111 Code: public boolean traverse(int row, int column) { if (valid(row, column)) { boolean done = false; grid[row][column] = TRIED; if (row == grid.length - 1 && column == grid[0].length - 1) done = true; else { done = traverse(row + 1, column); if(!done) done = traverse(row, column + 1); if(!done) done = traverse(row - 1, column); if(!done) done = traverse(row, column - 1); } if(done) grid[row][column] = PATH; } return done; } 21) Which of the following grids would be the result after traverse has completed all of its recursive calls? a) 1 1 1 1 1 100 00100100 001001 10 001 10010 00011000 000011 1 1 b) 3333330 0 0030030 0 0030033 0 0033003 0 0003300 0 0000333 3 c) 7773330 0 0070030 0 0070033 0 0077003 0 0007700 0 0000777 7 d) 7777770 0 0030070 0 0030077 0 0033007 0 0003300 0 0000333 3 e) 3337770 0 0030070 0 0030077 0 0033007 0 0003300 0 0000333 3
c Explanation: When a point in the maze is tried, its value is changed from 1 to 3, but if the end of the maze is found, the current row, column index is changed to 7. So the path is reflected as 7s and the tried but incorrect path is reflected as 3s and any untried parts of the path are reflected as 1s. For this maze, all legal path parts will have been tried before the solution is found, so the path leading to the exit is comprised of 7s and the remaining paths are comprised of 3s.
For questions 1 - 2, use the following recursive method. public int question1_2(int x, int y) { if (x == y) return 0; else return question1_2(x-1, y) + 1; } 2) Calling this method will result in infinite recursion if which condition below is initially true? a) (x = = y) b) (x != y) c) (x > y) d) (x < y) e) (x = = 0 && y != 0)
d Explanation: Of (x > y) is true initially, then the else cause is executed resulting in the method being recursively invoked with a value of x - 1, or a smaller value of x, so that (x < y) will be true again, and so for each successive recursive call, (x < y) will be true and the base case, x == y, will never be true.
17) If there are 6 disks to move from one Tower to another, how many disk movements would it take to solve the problem using the recursive solution? a) 6 b) 13 c) 31 d) 63 e) 127
d Explanation: The Towers of Hanoi solution requires using the previous solution twice + 1 extra move. To solve it for 1 disk, it takes 1 move. To solve it for 2 disks, it takes using the solution for 1 disk twice + 1 extra move, or 1 move + 1 move + 1 extra move = 3 moves. We capture this in the equation 2n - 1 where n is the number of disks. For 3 disks this takes 7 moves, for 4 disks this takes 15 moves, for 5 disks this takes 31 moves and for 6 disks this takes 63 moves.
16) If there are 2 disks to move from one Tower to another, how many disk movements would it take to solve the problem using the recursive solution? a) 0 b) 1 c) 2 d) 3 e) 4
d Explanation: The Towers of Hanoi solution requires using the previous solution twice + 1 extra move. To solve it for 1 disk, it takes 1 move. To solve it for 2 disks, it takes using the solution for 1 disk twice + 1, or 1 move + 1 move + 1 move = 3 moves. We capture this in the equation 2n - 1 where n is the number of disks.
18) The solution to the Towers of Hanoi has a(n) _____ complexity. a) linear b) polynomial c) logarithmic d) exponential e) bad
d Explanation: The complexity for Towers of Hanoi is 2n - 1, which is known as exponential because, as n increases by 1, the number of moves doubles, or the complexity increases exponentially.
For questions 19 - 21, consider the following representation of grid and the maze code from Chapter 8. Grid: 11111100 00100100 00100110 00110010 00011000 00001111 Code: public boolean traverse(int row, int column) { if (valid(row, column)) { boolean done = false; grid[row][column] = TRIED; if (row == grid.length - 1 && column == grid[0].length - 1) done = true; else { done = traverse(row + 1, column); if(!done) done = traverse(row, column + 1); if(!done) done = traverse(row - 1, column); if(!done) done = traverse(row, column - 1); } if(done) grid[row][column] = PATH; } return done; } 20) Assume at some point in processing, grid's row 0 has become 3 3 3 1 1 1 0 0. Which direction will next be tried? a) up b) down c) left d) right e) none, the recursion ends at this point
d Explanation: The current position is (2, 0), so it is not out of bounds or the lower right corner, and the current grid value was a 1, so the path is still valid. Therefore, the first instruction inside the else statement is executed, calling traverse with (row + 1, column) which represents the next position to the right.
22) Define the magnitude of a number as the location of the decimal point from the left of the number (that is, if a number has 4 digits followed by the decimal point, it will have a magnitude of 4). 100 would then have a magnitude of 3 and 55,555.555 would have a magnitude of 5. A partial recursive method is given below to compute a positive int parameter's magnitude. Which answer below is needed to complete the method? public int magnitude(double x) { if (x < 1) return 0; else return _______; } a) magnitude(x - 1) + 10; b) magnitude(x - 10) + 1; c) magnitude(x / 10) + 10; d) magnitude(x / 10) + 1; e) magnitude(x / 10) * 2;
d Explanation: The method must count the number of digits to the left of the decimal point, so it continually divides the value by 10 until the value has no digits to the left of the decimal point (this is the case if value < 1). Each time the value is divided by 10, 1 is added to the return value. 55,555.555 will be divided by 10 five times before it becomes < 1, and thus return 5.
The following method recognizes whether a String parameter consists of a specific pattern and returns true if the String has that pattern, false otherwise. Use this recursive method to answer questions 23 - 25. public boolean patternRecognizer(String a) { if(a == null) return false; else if (a.length( ) = = 1 | | (a.length( ) = = 2 && a.charAt(0) = = a.charAt(1) ) ) return true; else if (a.length( ) = = 2 && a.charAt(0) != a.charAt(1) ) return false; else if (a.charAt(0) == a.charAt(a.length( ) - 1)) return patternRecognizer(a.substring(1, a.length( ) - 1)); else return false; } 25) If the statement a.substring(1, a.length( ) - 1) were changed to be (a.substring(1, a.length( )), then the method would a) have infinite recursion unless the String were null b) always return true c) always return false d) return true only if all characters of the String were the same e) return true only the String had only two characters and they were the same
d Explanation: The original method recursively calls itself with a substring equal to the String minus the first and last characters. This new version would recursively call itself with a substring equal to the String minus the first character. The method would return true if the first character of the String (or substring) equaled the last character. Since the substring for each recursive call is the same as the previous String less the first character, it winds up comparing each character in the String to the last in the String and returning true only if each character of the String equals the last character. This means all of the characters are the same.
For questions 4 - 7, refer to the following recursive factorial method. public int factorial(int x) { if (x > 1) return x * factorial (x - 1); else return 1; } 4) What is returned if factorial(3) is called? a) 0 b) 1 c) 3 d) 6 e) 9
d Explanation: With factorial(3), x > 1, so it returns 3 * factorial(2), with factorial(2), x > 1 so it returns 2 * factorial(1), with factorial(1), 1 is returned, so we have 3 * 2 * 1 = 6.
For questions 9 - 13, assume that int[ ] a = {6, 2, 4, 6, 2, 1, 6, 2, 5} and consider the two recursive methods below foo and bar. public int foo(int[ ] a, int b, int j) { if (j < a.length) if (a[j] != b) return foo (a, b, j+1); else return foo (a, b, j+1) + 1; else return 0; } public int bar(int[ ] a, int j) { if (j < a.length) return a[I] + bar(a, j+1); else return 0; } 12) What is the result of calling bar(a, 0);? a) 0 b) 5 c) 6 d) 12 e) 34
e Explanation: The bar method recursively sums the elements of array a starting at the location of the second parameter. Since the starting point is location 0, this call sums all elements of a (which equals 34).
For questions 4 - 7, refer to the following recursive factorial method. public int factorial(int x) { if (x > 1) return x * factorial (x - 1); else return 1; } 7) What condition defines the base case for this method? a) (x > 1) b) (x = = 1) c) (x = = 0) d) (x <= 0) e) (x <= 1)
e Explanation: The if condition is (x > 1) but this is the recursive case, so the base case is the opposite condition. The opposite of (x > 1) is (x <= 1).