Table of Contents
Define the concept of recursion (Bloom 1*)
Describe the successive computations carried out when evaluating a recursive method (Bloom 2*)
Convert a tail-recursive method into iterative form (Bloom 3*)
Classify a recursive method into one of the types of recursion studied (Bloom 3*)
Given a recursive method, find the domain of convergence for some simple cases (Bloom 4)
Write down a recursive method for a given problem (Bloom 5)
Compare different recursive methods that solve the same problem (Bloom 6)
The following code that calculates the harmonic series is wrong,
and it will
eventually launch a
StackOverflowError
exception:
public double h(int n) { return h(n-1) + 1.0/n; }
The recursive harmonic function, even though with its base case
defined,
will still launching an
StackOverflowError
exception:
public double h(int n) { if (n==1) return 1.0; return h(n-1) + 1.0/n; }
A tail-recursion function can be converted into an iteration-based one. In a function, when there is a recursive call and this call is the last statement in the function, then this function can be converted into an iterative function. The next code has its iterative version immediately.
public void hanoi(int n,char from,char to,char ch) { if (n==1) System.out.println("Move 1 from"+from+"to"+to); else if (n>1) { hanoi(n-1, from, ch, to); System.out.println("Move "+n+"from"+from+"to"+ to); hanoi(n-1, ch,to, from); } }
Sometimes recursion is not efficient. For example, the Fibonacci series can be calculated
by the following recursive method.However, the time it takes grows exponentially with
n
, making this method useless, except for n
with small values.
public static long fib(int n) { if (n <= 1) return n; else return fib(n-1) + fib(n-2); } }with fib(0) = 0 and fib(1) = 1
The previous non-linear recursive method can be optimized for the Fibonacci series, transforming it into a linear recursive method more efficient.
In general, if there is a recursive method and an iterative method to solve the the same problem, it is preferred to use the iterative version due to efficiency.
A sorting algorithm, such as QuickSort, of logarithmic order, is always faster than one of quadratic order O(n^2), such as the BubbleSort, when n grows bigger.
If we are going to work with small values of n, the complexity order of the recursive algorithm is not significant and can be a problem instead.
Depending on the data size of an algorithm, the evolution of its temporal cost gets bigger, taking into account its complexity orders and its multiplying constants.
Backtracking algorithms are generally solved recursively.
You can verify if you have correctly implemented a recursive method by answering 3 questions about the base case and the non-base cases.
The "divide-and-conquer" technique using recursion, and applying it to the sorting algorithm "QuickSort", allows to diminish the average execution time to a logarithmic order O(log n).
Dynamic programming allows to solve sub-problems generated by a recursive design in a non-recursive version, storing the values of the solutions in a table.
The complexity of this piece of code is O(n^2)
for (int i = 0; i < n; i++) { for (int k = 0; k < i; i++) { m[i][k] = a[i] * a[k] } }