Chapter 20 - Recursion Flashcards
How to understand recursion?
Well, to understand recursion, you must first understand recursion.
What does it mean to use recursion?
To use recursion is to program using recursive methods – that is, to use methods that invoke themselves.
What is the “stopping condition” of a recursive method?
The base case, or stopping condition, is the simplest case – which the method knows how to solve directly – that ends the recursive method.
How can you write the factorial method using recursion?
public static long factorial(int n) { - if(n == 0) // base case - return 1; - else - return n * factorial(n - 1); // recursive call }
What will happen if the factorial method is written like this: public static long factorial(int n) { - return n * factorial(n - 1); } ?
The method runs infinitely and causes a StackOverflowError.
If recursion does not reduce the problem in a manner that allows it to eventually converge into the base case, infinite recursion can occur.
What is the difference between direct recursion and indirect recursion?
Direct recursion is when a method invokes itself.
Indirect recursion is when a method A invokes a method B, which in turn invokes method A again (in a circle). Indirect recursion may involve two or more methods.
Consider the recursive Fibonacci method: public static long fib(long index) { - if(index == 0) // base case - return 0; - else if(index == 1) // base case - return 1; - else // reduction and recursive calls - return fib(index - 1) + fib(index - 2); }
In what order are the recursive calls evaluated?
return fib(index - 1) + fib(index - 2)
In Java, operands are evaluated from left to right. Therefore, fib(index - 2) is called only after fib(index-1) is completely evaluated.
Should the Fibonacci series be computed using recursion or loops?
The recursive implementation of the fib method is very simple, but it isn’t efficient, since it requires more time and memory to run recursive methods. A more efficient solution could be made using loops. Though it is not practical, the recursive fib method is a good example of how to write recursive methods.
All recursive methods have 3 common characteristics. What are they?
The method is implemented using an if-else or a switch statement that leads to different cases.
One or more base cases (the simplest case) are used to stop recursion.
Every recursive call reduces the original problem, bringing it increasingly closer to a base case until it becomes that case.
In general, to solve a problem using recursion, you break it into subproblems, Each subproblem is the same as the original problem but smaller in size. You can apply the same approach to each subproblem to solve it recursively.
Thinking recursively, the problem of checking whether a string is a palindrome can be divided into two subproblems. What are they? What about the base case(s)?
The problem of checking whether a string is a palindrome can be divided into two subproblems:
- Check whether the first character and the last character of the string are equal.
- Ignore the two end characters and check whether the rest of the substring is a palindrome.
There are two base cases: (1) the two end characters are not the same, and (2) the string size is 0 or 1. In case 1, the string is not a palindrome; in case 2, the string is a palindrome.
What is a recursive helper method?
It is a common design technique in recursive programming to define a second method that receives additional parameters. Such a method is know as a recursive helper method.
Helper methods are very useful in designing recursive solutions for problems involving strings and arrays.
Give three common problems that are best solved using recursion.
- To find the size of a directory (size of all files and subdirectories).
- Tower of Hanoi.
- Displaying fractals (geometrical figure).
These problems are inherently recursive, and are difficult to solve without recursion.
What are some negative aspects of using recursion?
Any problem that can be solved recursively CAN be solved nonrecursively using loops. Recursion bears substantial overhead. Each time the program calls a method, the system must allocate memory for all of the method’s local variables and parameters. This can consume considerable memory and requires extra time to manage memory.
When should you use recursion?
In some cases, using recursion enables you to specify a clear, simple solution for an inherently recursive problem that would otherwise be difficult to obtain.
The decision whether to use recursion or iteration should be based on the nature of, and your understanding of, the problem you are trying to solve. The rule of thumb is to use whichever approach can best develop an intuitive solution that naturally mirrors the problem. If an iterative solution is obvious, use it. It will generally be more efficient than the recursive option.
What is a tail recursive method?
A recursive method is said to be tail recursive if there are no pending operations to be performed on return from a recursive call.
Tail recursive method: recursive method A { ...some code... ...some code... ...some code... Invoke method A recursively }
Nontail recursive method: recursive method B { ...some code... ...some code... Invoke method B recursively ...some code... }