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)