1、动态规划法
我们可以利用数组dp记录斐波那契数列中的每一个元素。
class Solution {
public:
int fib(int n) {
if (n < 2) return n;
vector<int> dp(n + 1, 0);
dp[1] = 1;
if (n < 2) return dp[0];
for (int i = 2; i <= n; ++i) {
dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
}
return dp[n];
}
};
2、动态规划法优化
考虑到实际上我们在使用斐波那契数组时只使用到数组的后两位,因此我们可以只使用三个变量记录数字从而优化空间复杂度。
class Solution {
public:
int fib(int n) {
int MOD = 1000000007;
if (n < 2) {
return n;
}
int p = 0, q = 0, r = 1;
for (int i = 2; i <= n; ++i) {
p = q;
q = r;
r = (p + q) % MOD;
}
return r;
}
};
3、矩阵快速幂
考虑到递推关系,我们可以构建下面的矩阵乘形式:
[
1
1
1
1
]
×
[
F
(
n
)
F
(
n
−
1
)
]
=
[
F
(
n
)
+
F
(
n
−
1
)
F
(
n
)
]
=
[
F
(
n
+
1
)
F
(
n
)
]
\begin{bmatrix}1&1 \\1 &1\end{bmatrix}\times \begin{bmatrix}F(n)\\F(n-1)\end{bmatrix}=\begin{bmatrix}F(n)+F(n-1)\\F(n)\end{bmatrix}=\begin{bmatrix}F(n+1)\\F(n)\end{bmatrix}
[1111]×[F(n)F(n−1)]=[F(n)+F(n−1)F(n)]=[F(n+1)F(n)]
我们可以得到:
[
F
(
n
+
1
)
F
(
n
)
]
=
[
1
1
1
0
]
n
[
F
(
1
)
F
(
0
)
]
\begin{bmatrix}F(n+1)\\F(n)\end{bmatrix}=\begin{bmatrix}1& 1\\1 &0\end{bmatrix}^n\begin{bmatrix}F(1)\\F(0)\end{bmatrix}
[F(n+1)F(n)]=[1110]n[F(1)F(0)]
因此只要我们能够得到
[
1
1
1
0
]
n
\begin{bmatrix}1& 1\\1 &0\end{bmatrix}^n
[1110]n的快速幂即可获得答案。
class Solution {
public:
const int MOD = 1000000007;
int fib(int n) {
if (n < 2) {
return n;
}
vector<vector<long>> q{{1, 1}, {1, 0}};
vector<vector<long>> res = pow(q, n - 1);
return res[0][0];
}
vector<vector<long>> pow(vector<vector<long>>& a, int n) {
vector<vector<long>> ret{{1, 0}, {0, 1}};
while (n > 0) {
if (n & 1) {
ret = multiply(ret, a);
}
n >>= 1;
a = multiply(a, a);
}
return ret;
}
vector<vector<long>> multiply(vector<vector<long>>& a, vector<vector<long>>& b) {
vector<vector<long>> c{{0, 0}, {0, 0}};
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j]) % MOD;
}
}
return c;
}
};