题意描述:
写一个函数,输入 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。
示例:
示例一:
输入:n = 2
输出:1
示例二:
输入:n = 5
输出:5
解题思路:
Alice: 这种题目有什么意思呢 ? 反正大家都会做。
Bob: hhhh, 这道题难度不在求斐波那契数列本身,难度在于怎样取余和防止溢出。
Alice: 这,换成 long
类型的还不够存吗 ?
Bob:恩,我试了,到 fn(95)
已经超过 long
的存储范围了。
Alice: 难不成还得写成大数加法 ? 那取余怎么办啊 ?
Bob: 不应该啊,这世道简单题,简单题这样做也太麻烦了。
Alice: 我想起来了!!取余的性质, (a + b) % p == (a % p + b % p)% p
Bob: 哦豁,那就OK了,递归来一遍,循环再来一遍绝对能过。
Alice:😎😎
代码:
Python 方法一: 递归 , 超时。
class Solution:
def fib(self, n: int) -> int:
return self.helper(n) % 1000000007
def helper(self, n: int) -> int:
if n < 2:
return n
else:
return self.helper(n-1) + self.helper(n-2)
Python 方法二: 循环
class Solution:
def fib(self, n: int) -> int:
if n < 2:
return n
else:
prepre = 0
pre = 1
for x in range(n-1):
ret = pre + prepre
prepre = pre
pre = ret
return ret % 1000000007
Java 方法一: 循环 + 加法对取余的分配律
class Solution {
public int fib(int n) {
if(n < 2){
return n;
}else{
long prepre = 0;
long pre = 1;
long ret = 0;
for(int i=0; i<n-1; ++i){
ret = prepre + pre;
prepre = pre % 1000000007;
pre = ret % 1000000007;
}
return (int)(ret % 1000000007);
}
}
}
易错点:
- 在求 fn(95) 的时候,中间计算结果 会超过 long 的存储范围。
总结:
- (a + b) % p = (a % p + b % p) % p
- 取余数的性质