MAT385 Recursion Examples
Fibonacci Numbers
The Fibonacci numbers are generally defined via the recursive algorithm
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2),
These numbers appear all over in nature: in pinecones, pineapples, artichokes, pussywillows, daisys, etc.
But they started out as pairs of immortal bunnies, which mature in a month, and then produce a single new pair every month thereafter:

This diagram illustrates why the recursive algorithm works:
- we assume that the number of bunny pairs arising from a single immature pair is given by the sequence F(n), with generations 1, 2, 3, ....
- We notice that at the third generation, the total population of pairs is given by the sum of two new populations: a perfect copy of the original tree, starting from the first generation, and a perfect copy of the original tree starting from the second generation.
- Hence
I class I presented the following algorithm in lisp for calculating the term in this sequence:
(defun fib(n) (case n ;; the following two cases are the basis cases: (1 1) (2 1) ;; and, if we're not in a basis case, then we should use recursion: (t (+ (fib (- n 1)) (fib (- n 2)))) ) )
If you calculate the ratio of successive Fibonacci numbers, , you notice something interesting happening:
n ratio 2 1 3 2 4 1.50000 5 1.66667 6 1.60000 7 1.62500 8 1.61538 9 1.61905 10 1.61765 11 1.61818 12 1.61798 13 1.61806 14 1.61803 15 1.61804 16 1.61803 17 1.61803 18 1.61803 19 1.61803 20 1.61803
It appears that the ratio as .
We can use this idea to find the closed form solution of F(n):
- assume that
- You can write as a linear combination of the two solutions:
- Check the formula for the first four Fibonacci numbers.
How many invocations?
As we were talking about computing the Fibonacci numbers via the recursive algorithm
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2),
we realized that the computations would grow excessively as n gets large. Consequently the time it takes to compute a Fibonacci number this way grows excessively long as n grows:
> (time (fib 20)) The evaluation took 0.02 seconds; 0.00 seconds in gc. 6765 > (time (fib 30)) The evaluation took 2.85 seconds; 0.05 seconds in gc. 832040 > (time (fib 35)) The evaluation took 31.61 seconds; 0.70 seconds in gc. 9227465
We argued this way: as soon as I go to calculate F(n), I need to invoke F two more times -- to compute F(n-1) and F(n-2). So it looks like the number of invocations is going to double each time. In addition, the invocation of F(n-1) is going to be wasteful, because it's going to invoke F(n-2) again (already invoked by F(n)). So we're redoing calculations -- very bad.
In class I asserted that the growth in the number of calculations is not really purely exponential. In this exercise, I want you to find out how bad it is. In order to do so, you need to find a recurrence relation for the number of invocations of F. Use a modified "expand, guess, check" strategy:
- How many times will you invoke F if n=1?
- How many times will you invoke F if n=2?
- How many times will you invoke F if n=3?
- How many times will you invoke F if n=4?
- How are the invocations of F at n related to the invocations of F at n-1 and n-2?
- Now, can you quickly write the first 10 terms in the sequence?
So why is it so easy to "recursively" write the first 10 terms? Because you're storing pairs.