原题
写一个函数,输入
n
,求斐波那契(Fibonacci)数列的第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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof
思路
Ⅰ. 斐波那契数列
- 斐波那契数列定义 f ( n + 1 ) = f ( n ) + f ( n − 1 ) f(n + 1) = f(n) + f(n - 1) f(n+1)=f(n)+f(n−1)
Ⅱ. 题目分析
此题一般都当作动态规划(Dynamic programming)入门题。
递归
我们可以直接用递归来解此题, 应该会超时。
我们看到,每一次递归都产生了大量的重复计算值,而这些值理论上我们只要计算一次。
时间复杂度 O ( 2 n ) O(2^n) O(2n),空间复杂度 O ( n ) O(n) O(n)
记忆保存
我们用一个数组保存,计算过的每个值,遇到了直接用就好了。
- c++代码
class Solution {
private:
long long vec[102];
public:
Solution() { fill_n(vec, 102, -1); }
int fib(int n) {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
return 1;
}
if (vec[n] != -1) {
return vec[n];
}
vec[n] = (fib(n - 1) + fib(n - 2)) % 1000000007;
return vec[n];
}
};
动态规划
我们以斐波那契数列性质 f ( n + 1 ) = f ( n ) + f ( n − 1 ) f(n + 1) = f(n) + f(n - 1) f(n+1)=f(n)+f(n−1) 为转移方程,写出代码即可。
- c++代码
class Solution {
public:
int fib(int n) {
vector<int> vec(n + 2);
vec[0] = 0;
vec[1] = 1;
for (int i = 2; i <= n; ++i) {
vec[i] = vec[i - 1] + vec[i - 2];
vec[i] %= 1000000007;
}
return vec[n];
}
};
- python 代码
class Solution:
def fib(self, n: int) -> int:
vec = [-1 for i in range(n + 2)]
vec[0] = 0
vec[1] = 1
for i in range(2, n + 1):
vec[i] = vec[i - 1] + vec[i - 2]
vec[i] %= 1000000007
return vec[n]
记忆保存和 DP 时间复杂度和空间复杂度都是 O ( n ) O(n) O(n)
Ⅲ. 优化
我们可不可以把空间复杂度优化成 O ( 1 ) O(1) O(1)
因为 C++可能会导致溢出,所以我们要找个变量。
- c++代码
class Solution {
public:
int fib(int n) {
int a = 0, b = 1;
for (int i = 0; i < n; ++i) {
int sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
}
};
- python 代码
python 整型数字没有限制,取决于计算机内存,应该可以理解为无限大。
class Solution:
def fib(self, n: int) -> int:
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a % 1000000007