1. 题目
[原题链接]写一个函数,输入 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
提示:0 <= n <= 100
注意:本题与LeetCode主站 509 题相同:https://leetcode-cn.com/problems/fibonacci-number/
2. 思路
斐波那契数列的定义是: f(n+1)=f(n)+f(n-1)
思路1:递归
把 f(n) 问题的计算拆分成 f(n-1) 和 f(n-2) 两个子问题的计算,并递归,以 f(0) 和 f(1) 为终止条件。标准递归法存在的缺点是存在大量重复的递归计算,例如 f(n) 和 f(n−1) 两者向下递归需要各自计算 f(n - 2) 的值,时间复杂度大。
![](https://img-blog.csdnimg.cn/20200922114658927.png?type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTQ4OTEx,size_16,color_FFFFFF,t_70#pic_center)
为了避免重复的递归计算,在标准递归法的基础上,新建一个长度为 n 的数组,用于在递归时存储 f(0) 至 f(n) 的数字值,当遇到某重复数字时可以直接从数组取用,不妨称之为记忆化递归法。但是该方法需要使用 O(N) 的额外空间,而且和标准递归法一样在提交时会超出时间限制。
思路2:动态规划
以斐波那契数列的定义为转移方程。
- 状态定义: 设 dp 为一维数组,其中 dp[i] 的值代表斐波那契数列第 i 个数字 。
- 转移方程: dp[i + 1] = dp[i] + dp[i - 1],即对应数列定义;
- 初始状态: dp[0] = 0, dp[1] = 1,即初始化前两个数字;
- 返回值: dp[n],即斐波那契数列的第 n 个数字。
3. 实现
思路1:递归
class Solution:
def fib(self, n: int) -> int:
# 标准递归法(超出时间限制)
#if n==0: return 0
#if n==1: return 1
#return (self.fib(n-1)+self.fib(n-2))%1000000007
# 记忆化递归法(超出时间限制)
#cache = [-1 for i in range(n+1)]
#if n == 0:return 0
#if n == 1:return 1
#if cache[n] == -1:
#cache[n] = self.fib(n-1) +self.fib(n-2)
#return cache[n]
若使用lru_cache( )
装饰器,可成功通过。
from functools import lru_cache
class Solution:
@lru_cache(None)
def fib(self, n: int) -> int:
if n ==0: return 0
if n == 1: return 1
return (self.fib(n - 1) + self.fib(n - 2)) % 1000000007
思路2:动态规划
class Solution:
def fib(self, n: int) -> int:
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a % 1000000007
4. 其它
- 题目难度:简单
- 相关题目:
- 相关要点:递归、动态规划