0509. 斐波那契数
大约 3 分钟
0509. 斐波那契数
- 标签:递归、记忆化搜索、数学、动态规划
- 难度:简单
题目链接
题目大意
描述:给定一个整数 。
要求:计算第 个斐波那契数。
说明:
- 斐波那契数列的定义如下:
- 。
- ,其中 。
- 。
示例:
- 示例 1:
输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
- 示例 2:
输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2
解题思路
思路 1:递归算法
根据我们的递推三步走策略,写出对应的递归代码。
- 写出递推公式:。
- 明确终止条件:。
- 翻译为递归代码:
- 定义递归函数:
fib(self, n)
表示输入参数为问题的规模 ,返回结果为第 个斐波那契数。 - 书写递归主体:
return self.fib(n - 1) + self.fib(n - 2)
。 - 明确递归终止条件:
if n == 0: return 0
if n == 1: return 1
- 定义递归函数:
思路 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)
思路 1:复杂度分析
- 时间复杂度:。具体证明方法参考 递归求斐波那契数列的时间复杂度,不要被网上的答案误导了 - 知乎。
- 空间复杂度:。每次递归的空间复杂度是 , 调用栈的深度为 ,所以总的空间复杂度就是 。
思路 2:动态规划算法
1. 划分阶段
我们可以按照整数顺序进行阶段划分,将其划分为整数 。
2. 定义状态
定义状态 为:第 个斐波那契数。
3. 状态转移方程
根据题目中所给的斐波那契数列的定义 ,则直接得出状态转移方程为 。
4. 初始条件
根据题目中所给的初始条件 确定动态规划的初始条件,即 。
5. 最终结果
根据状态定义,最终结果为 ,即第 个斐波那契数为 。
思路 2:代码
class Solution:
def fib(self, n: int) -> int:
if n <= 1:
return n
dp = [0 for _ in range(n + 1)]
dp[0] = 0
dp[1] = 1
for i in range(2, n + 1):
dp[i] = dp[i - 2] + dp[i - 1]
return dp[n]
思路 2:复杂度分析
- 时间复杂度:。一重循环遍历的时间复杂度为 。
- 空间复杂度:。用到了一维数组保存状态,所以总体空间复杂度为 。因为 的状态只依赖于 和 ,所以可以使用 个变量来分别表示 、、,从而将空间复杂度优化到 。