题目来源:力扣
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
一、递归
最容易想到的方法,也是一种很经典的解法,问题是时间复杂度为指数级,空间效率与时间效率都很低,面试官一般不喜欢,而且力扣也过不去。
下面展示 代码
。
int fib(int n) {
if (n == 0 || n == 1)
{
return n;
}
return fib(n - 1) + fib(n - 2);
}
二、动态规划
面试官能接受的一种方法,也是很常规的方法,首先创建一个数组存储斐波那契数列fib,然后遍历数组,利用递推式子
fib[i]=fib[i-1]+fib[i-2]填充数组。代码如下:
int fib(int n)
{
if (n <= 1)
return n;
vector<int> fib(n + 1);
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i <= n; i++)
{
fib[i] = fib[i - 1] + fib[i - 2];
}
return fib[n];
}
时间复杂度为O(n),空间复杂度也为O(n),相对于第一种递归法来说,时间效率略高。
三、改进递推
这种方法不太实用,但是能够使求解斐波那契数列的时间复杂度为对数级别,主要利用的是下式:
[
f
(
n
)
f
(
n
−
1
)
f
(
n
−
1
)
f
(
n
−
2
)
]
=
[
1
1
1
0
]
n
−
1
\begin{bmatrix}f(n) &f(n-1) \\ f(n-1)&f(n-2) \end{bmatrix}=\begin{bmatrix} 1&1 \\ 1&0 \end{bmatrix}^{n-1}
[f(n)f(n−1)f(n−1)f(n−2)]=[1110]n−1
将求解f(n)转换成求解矩阵的乘方,在求解乘方的时候,若只是简单的从0开始循环,时间复杂度仍然是O(n),但是可以考虑乘方的如下性质:
最终实现代码如下:
//创建目标矩阵
vector<vector<double>> creatmatrix()
{
vector<vector<double>> v;
vector<double>v1 = { 1,1 };
v.push_back(v1);
v1 = { 1,0 };
v.push_back(v1);
return v;
}
//矩阵A*矩阵B=矩阵C,并返回
vector<vector<double>> multiplybase(const vector<vector<double>>& A, const vector<vector<double>>& B)
{
int A_h = A.size();
int A_l = A[0].size();
int B_h = B.size();
int B_l = B[0].size();
if (A_l != B_h)
{
cout << "两矩阵维数无法相乘" << endl;
exit(0);
}
vector<vector<double>> C = creatmatrix(A_h, B_l);
for (int i = 0; i < A_h; i++)
{
for (int j = 0; j < B_l; j++)
{
C[i][j] = 0;
for (int k = 0; k < A_l; k++)
{
C[i][j] += A[i][k] * B[k][j];
}
//cout<<C[i][j]<<"\t";
}
//cout<<endl;
}
return C;
}
vector<vector<double>> multiply(const vector<vector<double>>& A, int n)
{
if (n == 1)
{
return A;
}
vector<vector<double>> temp = multiply(A, n / 2);
if (n % 2 == 1)
{
return multiplybase(multiplybase(temp, temp), A);
}
return multiplybase(temp, temp);
}
int fib(int n)
{
vector<vector<double>> base = creatmatrix(2, 2);
vector<double> result = multiply(base, n - 1)[0];
return result[0];
}
有关递归复杂度的讲解,请看
https://blog.csdn.net/weixin_60655522/article/details/126061250