📣🥳🥳🥳📣
✨Hello! 如果这篇【文章】对你有帮助😄,希望可以给博主点个赞👍鼓励一下😘
📣🥳🥳🥳📣
![](https://i-blog.csdnimg.cn/blog_migrate/ea718672e479fcff5b284a429a443821.jpeg)
🔎 题目描述
写一个函数,输入 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
📝 解题方法
【标签:递归、快速幂运算】
📌 递归法
class Solution {
public:
int fib(int n) {
if (n == 0 || n == 1) return n;
return (fib(n - 1) + fib(n - 2)) % 1000000007; //注意题目要求
}
};
递归法会超出时间限制要求,因此不可行。
📌 动态规划法
class Solution {
public:
int fib(int n) {
if (n == 0 || n == 1) return n;
int rear = 0, front = 1, temp = 0;
for (int i = 2; i <= n; ++i) {
temp = front;
front = (rear + front) % 1000000007; //注意题目要求
rear = temp;
}
return front;
}
};
下面这张动图源自Leetcode👇
时间复杂度O(N);
空间复杂度O(1)。
📌 快速幂运算法
这个方法需要用到矩阵的快速幂运算👇
设M如下👇
只需要算出M即可算出F(n)。因此这道题变成了:如何快速进行幂运算。
先不考虑矩阵的幂运算,对于常数,假设X=3,那么X9简单来说应该弄个循环体求个【9次】👇
int X = 3, result = 1;
for (int i = 1; i <= 8; ++i) { //一共需要运算9次
result *= X;
}
需要注意到的是,第一次运算时,产生了X2,可以直接使用,得到(X2)2=X4;这个结果也可以直接使用,因此第三次运算时产生了X8,以此类推其它项。因此有👇
于是我们只需要进行【4次】循环就可以得到运算结果。
可知时间复杂度从O(N)降低为O(log2N),即O(logN)。
对矩阵幂运算同理,只需要将X换成矩阵即可。具体程序如下👇
class Solution {
public:
int fib(int n) {
if (n == 0 || n == 1) return n;
vector<vector<long>> matrix_m = {{1, 1}, {1, 0}}; //用long类型的原因可以在子函数matrix_multiply中看到
vector<vector<long>> matrix_mn = matrix_pow(matrix_m, n - 1);
return matrix_mn[0][0]; //return matrix_mn[0][0] * f(1) + matrix_mn[0][1] * f(0)
}
//matrix_pow函数:2×2矩阵的幂运算操作
vector<vector<long>> matrix_pow(vector<vector<long>> &vvec, int n) { //采用传引用可以降低复制开销
vector<vector<long>> result = {{1, 0}, {0, 1}}, temp = vvec; //后面涉及累乘,result初始化为单位阵
while (n != 0) {
if (n & 1) result = matrix_multiply(result, temp); //n & 1为二进制按位与,即n的二进制形式和0000 0001进行与操作
temp = matrix_multiply(temp, temp); //这里循环生成2次方,4次方,8次方, …………
n >>= 1; //右移一位
}
return result;
}
//matrix_multiply函数:2×2矩阵的相乘运算操作
vector<vector<long>> matrix_multiply(vector<vector<long>> &x, vector<vector<long>> &y) {
vector<vector<long>> result = {{0, 0}, {0, 0}}; //一开始这里没有初始化,下面进行索引就会报reference binding to null pointer of type
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
result[i][j] = (x[i][0] * y[0][j] + x[i][1] * y[1][j]) % 1000000007; //这里就是用long的原因,括号内的运算会超出int的范围(int占4个字节32位,2^32的值不超过43亿)
}
}
return result;
}
};
子函数
matrix_multiply
里忘记对result
进行初始化报reference binding to null pointer of type
,见【runtime error: reference binding to null pointer of type ‘int‘ (stl_vector.h)的报错】
时间复杂度O(logN);
空间复杂度O(1)。
✨如有问题欢迎在底下评论留言或私信!
如果这篇【文章】对你有帮助😄,希望可以给博主【点个赞👍】鼓励一下😘
❤️Thanks for your encouragement❤️