Problem: Find Nth fibonacci number in O(logN) time complexity.
Fibonacci Series: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
Method 2: As in above algorithm, we are processing for same sub-problem many times. Hence we follow dynamic approach to avoid calculation of same sub-problem again and again.
Method 3: Most optimized solution:
We all know the Fibonacci recurrence as F(n+1) = F(n) + F(n-1) but we can represent this in the form a matrix as shown below:
Look at the matrix A = [ [ 1 1 ] [ 1 0 ] ] . Multiplying A with [ F(n) F(n-1) ] gives us [ F(n+1) F(n) ] , so we say that
start with [ F(1) F(0) ] , multiplying it with A gives us [ F(2) F(1) ]; again multiplying [ F(2) F(1) ] with A gives us [ F(3) F(2) ] and so on ...
Following is the code:
Fibonacci Series: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
F(n) = F(n-1) + F(n-2) with initial values: F(0) = 0 and F(1) = 1For example:
Input: n = 9 Output: 34Method 1: A simple method that is a direct recursive implementation mathematical recurrence relation given above.
class InterviewDesk
{
/* method to return required result */
static int fibonacci(int n)
{
/* handling base condition */
if (n <= 1)
return n;
return
fibonacci(n-1) + fibonacci(n-2);
}
/* driver method */
public static void main (String args[])
{
int n = 9;
System.out.println(fibonacci(n));
}
}
Output:
34Time Complexity: Exponential
Method 2: As in above algorithm, we are processing for same sub-problem many times. Hence we follow dynamic approach to avoid calculation of same sub-problem again and again.
class InterviewDesk
{
/* method to return required result */
static int Fibonacci(int n)
{
int a = 0, b = 1, c;
/* handling base case */
if (n == 0)
return a;
for (int i = 2; i <= n; i++)
{
c = a + b;
a = b;
b = c;
}
return b;
}
/* driver method */
public static void main (String args[])
{
int n = 9;
System.out.println(Fibonacci(n));
}
}
Output:
34Time Complexity: O(n) and Space Complexity: O(1)
Method 3: Most optimized solution:
We all know the Fibonacci recurrence as F(n+1) = F(n) + F(n-1) but we can represent this in the form a matrix as shown below:
Look at the matrix A = [ [ 1 1 ] [ 1 0 ] ] . Multiplying A with [ F(n) F(n-1) ] gives us [ F(n+1) F(n) ] , so we say that
A* [ F(n) F(n-1) ] = [ F(n+1) F(n) ]
start with [ F(1) F(0) ] , multiplying it with A gives us [ F(2) F(1) ]; again multiplying [ F(2) F(1) ] with A gives us [ F(3) F(2) ] and so on ...
A* [ F(1) F(0) ] = [ F(2) F(1) ] A* [ F(2) F(1) ] = [ F(3) F(2) ] = A^2 * [ F(1) F(0) ] A* [ F(3) F(2) ] = [ F(4) F(3) ] = A^3 * [ F(1) F(0) ] . . . . A* [ F(n) F(n-1) ] = [ F(n+1) F(n) ] = A^n * [ F(1) F(0) ]So all that is left is finding the nth power of the matrix A. Well, this can be computed in O(log n) time, by recursive doubling. The idea is, to find A^n , we can do R = A^(n/2) * A^(n/2) and if n is odd, we need do multiply with an A at the end.
Following is the code:
class InterviewDesk
{
/* method to return required result */
static int fib(int n)
{
int F[][] = new int[][]{{1,1},{1,0}};
if (n == 0)
return 0;
power(F, n-1);
return F[0][0];
}
/* method to multiply 2 matrices F and M of size 2*2, and
puts the multiplication result back to F[][] */
static void multiply(int F[][], int M[][])
{
int x = F[0][0]*M[0][0] + F[0][1]*M[1][0];
int y = F[0][0]*M[0][1] + F[0][1]*M[1][1];
int z = F[1][0]*M[0][0] + F[1][1]*M[1][0];
int w = F[1][0]*M[0][1] + F[1][1]*M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/* method that calculates F[][] raise to the power n and puts the
result in F[][] */
static void power(int F[][], int n)
{
int i;
int M[][] = new int[][]{{1,1},{1,0}};
/* n - 1 times multiply the matrix to {{1,0},{0,1}} */
for (i = 2; i <= n; i++)
multiply(F, M);
}
/* driver method */
public static void main (String args[])
{
int n = 9;
System.out.println(fib(n));
}
}
Output:
34Time Complexity: O(logn)
