Write a function int fib(int n) that returns .
Method 2 ( Use Dynamic Programming )
Method 3 ( Space Otimized Method 2 )
Method 4 ( Using power of the matrix {{1,1},{1,0}} )
Method 5 ( Optimized Method 4 )
The method 4 can be optimized to work in O(Logn) time complexity. We can do recursive multiplication to get power(M, n) in the previous method.
http://www.geeksforgeeks.org/matrix-exponentiation/
What is the minimum time complexity to find n’th Fibonacci Number?
We can find n’th Fibonacci Number in O(Log n) time using Matrix Exponentiation.
Ways to represent a number as a sum of 1’s and 2’s
Read full article from Program for Fibonacci numbers | GeeksforGeeks
Method 2 ( Use Dynamic Programming )
f[0] = 0;
f[1] = 1;
for
(i = 2; i <= n; i++)
{
/* Add the previous 2 numbers in the series
and store it */
f[i] = f[i-1] + f[i-2];
}
return
f[n];
int
fib(
int
n)
{
int
a = 0, b = 1, c, i;
if
( n == 0)
return
a;
for
(i = 2; i <= n; i++)
{
c = a + b;
a = b;
b = c;
}
return
b;
}
This another O(n) which relies on the fact that if we n times multiply the matrix M = {{1,1},{1,0}} to itself (in other words calculate power(M, n )), then we get the (n+1)th Fibonacci number as the element at row and column (0, 0) in the resultant matrix.
The matrix representation gives the following closed expression for the Fibonacci numbers:
int
fib(
int
n)
{
int
F[2][2] = {{1,1},{1,0}};
if
(n == 0)
return
0;
power(F, n-1);
return
F[0][0];
}
void
power(
int
F[2][2],
int
n)
{
int
i;
int
M[2][2] = {{1,1},{1,0}};
// n - 1 times multiply the matrix to {{1,0},{0,1}}
for
(i = 2; i <= n; i++)
multiply(F, M);
}
The method 4 can be optimized to work in O(Logn) time complexity. We can do recursive multiplication to get power(M, n) in the previous method.
int
fib(
int
n)
{
int
F[2][2] = {{1,1},{1,0}};
if
(n == 0)
return
0;
power(F, n-1);
return
F[0][0];
}
/* Optimized version of power() in method 4 */
void
power(
int
F[2][2],
int
n)
{
if
( n == 0 || n == 1)
return
;
int
M[2][2] = {{1,1},{1,0}};
power(F, n/2);
multiply(F, F);
if
(n%2 != 0)
multiply(F, M);
}
void
multiply(
int
F[2][2],
int
M[2][2])
{
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;
}
What is the minimum time complexity to find n’th Fibonacci Number?
We can find n’th Fibonacci Number in O(Log n) time using Matrix Exponentiation.
F(n) = a*F(n-1) + b*F(n-2) + c*F(n-3) for n >= 3 . . . . . Equation (1) where a, b and c are constants. For this recurrence relation it depends on three previous values. Now we will try to represent Equation (1) in terms of matrix. [First Matrix] = [Second matrix] * [Third Matrix] | F(n) | = Matrix 'C' * | F(n-1) | | F(n-1) | | F(n-2) | | F(n-2) | | F(n-3) | Dimension of the first matrix is 3 x 1 . Dimension of third matrix is also 3 x 1. So the dimension of the second matrix must be 3 x 3 [For multiplication rule to be satisfied.] Now we need to fill the Matrix 'C'. So according to our equation. F(n) = a*F(n-1) + b*F(n-2) + c*F(n-3) F(n-1) = F(n-1) F(n-2) = F(n-2) C = [a b c 1 0 0 0 1 0] Now the relation between matrix becomes : [First Matrix] [Second matrix] [Third Matrix] | F(n) | = | a b c | * | F(n-1) | | F(n-1) | | 1 0 0 | | F(n-2) | | F(n-2) | | 0 1 0 | | F(n-3) | Lets assume the initial values for this case :- F(0) = 0 F(1) = 1 F(2) = 1 So, we need to get F(n) in terms of these values. So, for n = 3 Equation (1) changes to | F(3) | = | a b c | * | F(2) | | F(2) | | 1 0 0 | | F(1) | | F(1) | | 0 1 0 | | F(0) |
void
multiply(
int
a[3][3],
int
b[3][3])
{
// Creating an auxiliary matrix to store elements
// of the multiplication matrix
int
mul[3][3];
for
(
int
i = 0; i < 3; i++)
{
for
(
int
j = 0; j < 3; j++)
{
mul[i][j] = 0;
for
(
int
k = 0; k < 3; k++)
mul[i][j] += a[i][k]*b[k][j];
}
}
// storing the muliplication resul in a[][]
for
(
int
i=0; i<3; i++)
for
(
int
j=0; j<3; j++)
a[i][j] = mul[i][j];
// Updating our matrix
}
// Function to compute F raise to power n-2.
int
power(
int
F[3][3],
int
n)
{
int
M[3][3] = {{1,1,1}, {1,0,0}, {0,1,0}};
// Multiply it with initial values i.e with
// F(0) = 0, F(1) = 1, F(2) = 1
if
(n==1)
return
F[0][0] + F[0][1];
power(F, n/2);
multiply(F, F);
if
(n%2 != 0)
multiply(F, M);
// Multiply it with initial values i.e with
// F(0) = 0, F(1) = 1, F(2) = 1
return
F[0][0] + F[0][1] ;
}
// Return n'th term of a series defined using below
// recurrence relation.
// f(n) is defined as
// f(n) = f(n-1) + f(n-2) + f(n-3), n>=3
// Base Cases :
// f(0) = 0, f(1) = 1, f(2) = 1
int
findNthTerm(
int
n)
{
int
F[3][3] = {{1,1,1}, {1,0,0}, {0,1,0}} ;
return
power(F, n-2);
}
Ways to represent a number as a sum of 1’s and 2’s
Given a positive integer N. The task is to find the number of ways of representing N as a sum of 1s and 2s.
For N = 1, answer is 1.
For N = 2. (1 + 1), (2), answer is 2.
For N = 3. (1 + 1 + 1), (2 + 1), (1 + 2), answer is 3.
For N = 4. (1 + 1 + 1 + 1), (2 + 1 + 1), (1 + 2 + 1), (1 + 1 + 2), (2 + 2) answer is 5.
And so on.
For N = 2. (1 + 1), (2), answer is 2.
For N = 3. (1 + 1 + 1), (2 + 1), (1 + 2), answer is 3.
For N = 4. (1 + 1 + 1 + 1), (2 + 1 + 1), (1 + 2 + 1), (1 + 1 + 2), (2 + 2) answer is 5.
And so on.
It can be observe that it form Fibonacci Series. So, the number of ways of representing N as a sum of 1s and 2s is (N + 1)th Fibonacci number.
How ?
We can easily see that the recursive function is exactly same as Fibonacci Numbers. To obtain the sum of N, we can add 1 to N – 1. Also, we can add 2 to N – 2. And only 1 and 2 are allowed to make the sum N. So, to obtain sum N using 1s and 2s, total ways are: number of ways to obtain (N – 1) + number of ways to obtain (N – 2).
How ?
We can easily see that the recursive function is exactly same as Fibonacci Numbers. To obtain the sum of N, we can add 1 to N – 1. Also, we can add 2 to N – 2. And only 1 and 2 are allowed to make the sum N. So, to obtain sum N using 1s and 2s, total ways are: number of ways to obtain (N – 1) + number of ways to obtain (N – 2).
We can find N’th Fibonacci Number in O(Log n) time
void
multiply(
int
F[2][2],
int
M[2][2])
{
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;
}
// Power function in log n
void
power(
int
F[2][2],
int
n)
{
if
( n == 0 || n == 1)
return
;
int
M[2][2] = {{1,1},{1,0}};
power(F, n/2);
multiply(F, F);
if
(n%2 != 0)
multiply(F, M);
}
/* function that returns (n+1)th Fibonacci number
Or number of ways to represent n as sum of 1's
2's */
int
countWays(
int
n)
{
int
F[2][2] = {{1,1},{1,0}};
if
(n == 0)
return
0;
power(F, n);
return
F[0][0];
}