剑指 Offer 10- I. 斐波那契数列
写一个函数,输入 n
,求斐波那契(Fibonacci)数列的第 n
项(即 F(N)
)。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:1
示例 2:
输入:n = 5
输出:5
提示:
0 <= n <= 100
方法一:递归法
过于简单,略过。
方法二:滚动数组
我们要表现的始终都是 F(n+1),F(n)和F(n−1)F(n+1),F(n)和F(n-1)F(n+1),F(n)和F(n−1)三个数之间的关系,所以我们只需要用三个数来滚动表示他们即可:
代码如下:
Class Solution{
static final int MOD = 100000007;
int Fib(int n){
int p=0, q=0, r=1;
for(int i=0; i<n; i++){
p = q;
q = r;
r = (p + q) % MOD;
}
return q;
}
}
- 时间复杂度:O(n)。
- 空间复杂度:O(1)。
方法三:矩阵的快速幂
通过矩阵的快速幂来降低时间复杂度:
构建等式:
因此
代码如下:
class Solution {
//模
public static final int MOD = 1000000007;
//主函数
public int fib(int n) {
if(n < 2){return n;}
int[][] q = {{1,1},{1,0}};
int[][] result = pow(q, n-1);
return result[0][0];
}
//计算快速幂的方法
public int[][] pow(int[][] a, int n){
int[][] ret = {{1,0},{0,1}};
while(n>0){
if((n&1) == 1){
ret = multiply(ret, a);
}
n = n >> 1;
a = multiply(a, a);
}
return ret;
}
//定义矩阵乘法
public int[][] multiply(int[][] a, int[][] b){
int [][] c = new int[2][2];
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
c[i][j] = (int)(((long)a[i][0]*b[0][j]+(long)a[i][1]*b[1][j])%MOD);
}
}
return c;
}
}