509.斐波那契数【动态规划】

这篇博客详细介绍了如何使用动态规划解决斐波那契数列的问题,包括动规五部曲的解析和优化后的空间复杂度。此外,还提到了递归解法及其时间复杂度。动态规划是解决具有重叠子问题的有效方法,通过状态推导和举例说明了动态规划的解题过程。
摘要由CSDN通过智能技术生成

509. 斐波那契数

题目地址:https://leetcode-cn.com/problems/fibonacci-number/
斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你n ,请计算 F(n) 。

示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:
输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:
输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3
 
提示:

0 <= n <= 30

思路
斐波那契数列大家应该非常熟悉不过了,非常适合作为动规第一道题目来练练手。

动态规划
动规五部曲:

这里我们要用一个一维dp数组来保存递归的结果

1. 确定dp数组以及下标的含义

dp[i]的定义为:第i个数的斐波那契数值是dp[i]

2. 确定递推公式

题目已经把递推公式直接给我们了:状态转移方程 dp[i] = dp[i - 1] + dp[i - 2];


3. dp数组如何初始化
题目中把如何初始化也直接给我们了,如下:
dp[0] = 0;
dp[1] = 1;

4. 确定遍历顺序
从递归公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历的

5. 举例推导dp数组
按照这个递推公式dp[i] = dp[i - 1] + dp[i - 2],我们来推导一下,当N为10的时候,dp数组应该是如下的数列:
0 1 1 2 3 5 8 13 21 34 55

如果代码写出来,发现结果不对,就把dp数组打印出来看看和我们推导的数列是不是一致的。

以上我们用动规的方法分析完了,Java代码如下:

时间复杂度:O(n)
空间复杂度:O(n)

继续优化,我们其实只需要维护两个数值就可以了,不需要记录整个序列。

时间复杂度:O(n)
空间复杂度:O(1)

递归解法
本题还可以使用递归解法来做

时间复杂度:O(2^n)
空间复杂度:O(n)

什么是动态规划

动态规划,英⽂:Dynamic Programming,简称DP,如果某⼀问题有很多重叠⼦问题,使⽤动态规划是最有效的。

动态规划中每⼀个状态⼀定是由上⼀个状态推导出来的,这⼀点就区分于贪⼼,贪⼼没有状态推导,⽽是从局部直接选最优的。

动规和贪心的区别举个例子:

例如:有N件物品和⼀个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能⽤⼀次,求解将哪些物品装⼊背包⾥物品价值总和最⼤。

动态规划中dp[j]是由dp[j-weight[i]]推导出来的,然后取max(dp[j], dp[j - weight[i]] + value[i])。

但如果是贪⼼呢,每次拿物品选⼀个最⼤的或者最⼩的就完事了,和上⼀个状态没有关系。 

动态规划的解题步骤:

对于动态规划问题,可以拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值