一、题目:
斐波那契数列
写一个函数,输入 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
二、题解:1.解读
从题目可以发现属于数学推导式,如果知道数学中的归纳法,不凡先看看它的规律。
n=0------> f(0)=0
n=1------> f(1)=1
n=2------> f(2)=f(0)+f(1)=1
n=3------> f(3)=f(2)+f(1)=2
F(N) = F(N - 1) + F(N - 2)
可以发现0和1相当于初始化数,后者依次等于前面两数之和,出现了递推的关系,故想到使用动态规划。
2.思路
确认了使用动态规划,则直接写出方程dp[i]=fun(dp[i-1],dp[i-2].....dp[i-m])。不过使用Dp的时候还是需要注意一下几点
- 清楚dp的定义,这里的dp[i]代表什么含义
- 确定状态转移方程,各个子问题之间的关系
- 初始化dp数组
- 模拟求解
3.实现
有了思路,我们下面开始详细写写实现过程
- 确定此处dp的含义:dp为斐波那契数列记录数组,其中dp[i]表示下标为i的值
- 确定状态转移方程,题目直接给出了转移方程的关系,即第n项的值为前两项的和,dp[i]=dp[i-1]+dp[i-2]
- 初始化dp数组,条件已满足,即dp[0] = 0,dp[1] = 1
- 模拟求解
三、代码:
class Solution:
def fib(self, n: int) -> int:
# 边界判断
if(n<=1):
return n
# 第一步 确定dp[i]含义: 表示第i个对应的斐波那契数
# 第二步 状态转移方程 dp[i] = dp[i-1] + dp[i-2]
dp = [0]*(n+1)
#第三步 初始化
dp[0] = 0
dp[1] = 1
# S4 模拟递归
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[i]%1000000007
时间复杂度:O(n) 二分查找的时间复杂度
空间复杂度:O(1) 使用了常数个空间
四、总结
采用动态规划的方式是因为自己想加强对动态规划的理解,其实还有其他诸如尾递归的方式。