1. Introduction to Recursion - general description - examples - linear recursive process General Description Recursion is an important problem solving technique. Recursion is applied to problems that exhibit self-similarity. That is, it is applied to problems whose solutions can be expressed in terms of solutions to similar but smaller subproblems. Similar and smaller are the essential ingredients: - similar implies that recursion can be applied to solve the problem - smaller implies that as we search deeper for a solution eventually we will get to a very simple instance of the problem that can be solved directly Recursive solutions typically are very clear and appear deceptively simple. In fact many problems can be solved quite easily with recursion and would be impossible to solve with the tools that we have up to this point. Note: - All of the methods we have written so far can be rewritten to use recursion. - For some problems recursion is more natural; others are clearer to express with loops. In a programming language recursion uses the fact that a method can call itself. We need to structure the code in such a way, that every time the method calls itself, it is going to work on a problem of "smaller size" where the notion of "size" depends on the problem that is being solved. Example -- Adding Integers The classic example of recursion is adding the numbers from 1..n.
Goal: Write a method called sum(n) which takes one parameter n and returns the sum of all integers in the range [1..n], i.e, the method computes: 1 + 2 + 3 + ... + n
A "lazy" way of solving the problem would be to say:
To sum the numbers from 1 to n, simply add n to the sum of the numbers from 1 to n-1.
Even though this seems to restate the main problem, there is a crucial difference. The second time we are asked to find the sum of fewer numbers, i.e. we need to solve a simpler (smaller) subproblem. If we keep thinking/telescoping in this way, eventually we would get to the simple case of adding the numbers from 1 to 1, which is just 1. Another way to summarize this is as follows:
Let Sum(n) denote the sum of the numbers from 1 to n. Then, Easy Case: Sum(1) = 1 Recursive Case: Sum(n) = n + Sum(n-1)
In Java this can be expressed as follows:

// computes the sum of the integers from 1 to n 

int sum( int n )
{
    if ( n == 1 )
    {
        return 1;                   // Easy/Base Case
    }
    else
    {
        return n + sum( n - 1 );    // Hard/Recursive Case
    }
}
Here is a trace of the execution of the code for n = 5:

  sum(5) = 15
   |       ^___________
   V                   \
 5 + sum(4) = 5 + 10 = 15
      |           ^_____
      V                 \
    4 + sum(3) = 4 + 6 = 10
         |           ^_____
         V                 \
       3 + sum(2) = 3 + 3 = 6
            |           ^_____
            V                 \
          2 + sum(1) = 2 + 1 = 3
               |           ^
               V           |
               1  _________|
At each step, Java attempts to evaluate a new value for sum. As it moves down during the recursive calls, Java "remembers" the computations that are waiting to be evaluated. Eventually, the base case is reached (this is the case that is easy to evaluate), and then the values of deferred computations are sent back up the recursion chain.
The above computational process is called LINEAR recursive. It is a recursive process and the shape of the computation looks like a diagonal line.
Example -- Exponentiation The process of exponentiation has a natural recursive description. It is somewhat analogous to the process of computing the sum of the integers from 1 to n.
Goal: Write a recursive method called power(b, n) which raises the real number b to the integer power n.
Here is the recursive description of the process of exponentiation:
Base Case: b0 = 1 Recursive Step: bn = b * bn-1
Here is the Java code based on the above description:

double power( double b, int n )
{
    if ( n == 0 )
    {
        return 1;                        // Base Case
    }
    else
    {
        return b * power( b, n - 1 );    // Recursive Step
    }
}
Here is a trace of the execution of the code for b = 2, n = 4:

 power(2, 4) = 16
   |           ^__________
   V                      \
 2 * power(2, 3) = 2 * 8 = 16
       |               ^______
       V                      \
     2 * power(2, 2) = 2 * 4 = 8
           |               ^______
           V                      \
         2 * power(2, 1) = 2 * 2 = 4
               |               ^______
               V                      \  
             2 * power(2, 0) = 2 * 1 = 2
                   |               ^  
                   V               |
                   1 ______________|