Introduction:This article first explains how to implement recursive
fibonacci algorithm in java, and follows it up with an enhanced
algorithm implementation of recursive fibonacci in java with
memoization.
What is Fibonacci Sequence: Fibonacci is the sequence of numbers
which are governed by the recurrence relation – “F(n)=F(n-1)+F(n-
2)”.
The first 2 numbers numbers in the sequence are 0,1 . The Fibonacci
sequence, based on the recurrence relation given above, goes like this
– 0,1,1,2,3,5,8,13,21 and so on…
Recursive Fibonacci Implementation: Given below is
a recursive java program which generates numbers in the
Fibonacci sequence –
Recursive Fibonacci Implementation
public class Fibonacci {
public static long fibonacci(long n) {
if(n==0 ){
return 0;
}else if(n==1){
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
public static void main(String args[]) {
long preTime=System.currentTimeMillis();
System.out.println("Value of 25th number in fibonacci series->"+fibonacci(25));
long postTime=System.currentTimeMillis();
System.out.println("Time taken to compute in milliseconds->"+(postTim
preTime));
}
}
Output for the above program
Value of 25th number in Fibonacci series->121393
Time taken to compute in milliseconds->10
In the above program the Fibonacci calculation is done in the method
fibonacci() which takes as input a single parameter of type long (long
n), and returns the number at the nth position in the Fibonacci series.
As you must have noticed, the method is recursive in nature and calls
itself twice for computing Fibonacci numbers at the position ‘n’ and ‘n-
1’. It then adds up these 2 values which is in line with the recurrence
relation describing Fibonacci numbers.
The program also computes and prints out the time taken in
determining this number. In this case (n=25), time taken was 10
milliseconds. Lets run this program for n > 25 and see how much time
it takes. For n=30 (17 ms), n=35 (105 ms), n=40 (1023 ms),
n=45(12083 ms), n=46 (17872 ms), n=48 (30889 ms). As you can
see, the time taken is increasing at an alarming rate because the
number of recursive calls are increasing at a very high rate with every
increase in the value of n.
This deterioration in performance can be improved by an optimization
technique called Memoization. In Memoization the results of expensive
function calls, i.e. functions which take a lot of time, are cached on
their first run. These cached values are then re-used when the function
is called again with the same inputs.
Recursive Fibonacci Implementation using Memoization: Given
below is a recursive java program for Fibonacci generation which
utilizes the concept of memoization to improve its performance –
Recursive Fibonacci Implementation using Memoization
public class FibonacciWithMemoization {
public static long fibArray[]=new long[26];
public static long fibonacci(long n){
long fibValue=0;
if(n==0 ){
return 0;
}else if(n==1){
return 1;
}else if(fibArray[(int)n]!=0){
return fibArray[(int)n];
}else{
fibValue=fibonacci(n-1)+fibonacci(n-2);
fibArray[(int) n]=fibValue;
return fibValue;
}
}
public static void main(String args[]){
fibArray[0]=0;
fibArray[1]=1;
long preTime=System.currentTimeMillis();
System.out.println("Value of 25th number in Fibonacci series->"+fibonacci(25));
long postTime=System.currentTimeMillis();
System.out.println("Time taken to compute in milliseconds->"+(postTime-preTime));
}
}
Output for the above program
Value of 25th number in Fibonacci series->121393
Time taken to compute in milliseconds->0
As you can see in the above program, the value of every fibonacci
number at position ‘n’ is being stored in an array called ‘fibArray’ at
position ‘n’. At the first instance of calling fibonacci(n), the result is
also stored in fibArray[n]. Next time when this value is needed again
then instead of calculating this value again recursively, the program
simply picks it up from the array. It comes to know whether a value is
cached or not simply by checking if the value is not zero.
Using memoization, the performance improves drastically. I checked
for n=30, n=50, n=80, n=120 and so on. The time taken kept coming
as 0 ms. It was around n=150 that the time taken increased to 1 ms.
Compared to time taken without Memoization, this is a very good.