当前位置: 首页 > news >正文

代码随想录第28天:动态规划1

一、什么是动态规划

Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。

动态规划中每一个状态一定是由上一个状态推导出来的,而贪心没有状态推导,而是从局部直接选最优的。

解决动态规划问题的五部思考流程,代码随想录Carl总结为“动规五部曲”:

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

做动规的题目,写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍,如果代码没通过就打印dp数组,找出哪里和自己预先推导的不一样。如果和自己预先模拟推导是一样的,那就是递归公式、初始化或者遍历顺序有问题,如果和自己预先模拟推导的不一样,那么大概率是代码实现细节有问题。

二、斐波那契数(Leetcode 509)

class Solution:def fib(self, n: int) -> int:# 边界情况处理:如果n为0,直接返回0if n == 0:return 0# 创建一个大小为n+1的列表,用来存储从0到n的Fibonacci数dp = [0] * (n + 1)# dp数组初始化:dp[0] = 0 和 dp[1] = 1dp[0], dp[1] = 0, 1 # 从第2个元素开始,计算Fibonacci数列的每个数for i in range(2, n + 1):# 递推公式:dp[i]是dp[i-1]和dp[i-2]的和,即Fibonacci数列的定义dp[i] = dp[i - 1] + dp[i - 2]# 返回第n个Fibonacci数return dp[n]

三、爬楼梯(Leetcode 70)

1.确定dp数组以及下标的含义:达到  i 阶有dp[i] 种方法

2.确定递推公式:

dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,下一步跳一个台阶就是dp[i]。

dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,下一步跳两个台阶就是dp[i]。

那么dp[i]就是 dp[i - 1]与dp[i - 2]之和

dp[i] = dp[i - 1] + dp[i - 2]

3.dp数组如何初始化:dp[0] = 1(没有实际意义)dp[1] = 1, dp[2] = 2

4.确定遍历顺序:从前向后遍历

5.举例推导dp数组(debug用)

class Solution:def climbStairs(self, n: int) -> int:# 如果楼梯的级数小于等于1,直接返回n# 即:如果楼梯有0级或1级,只有一种方式(直接站着或爬一步)if n <= 1:return n# 初始化一个大小为n+1的dp数组,用来存储从0到n级台阶的方法数dp = [0] * (n + 1)# 基础情况:# dp[1]表示爬到第1级台阶有1种方法(一步到达)# dp[2]表示爬到第2级台阶有2种方法(一步一步爬,或者一次爬两步)dp[1] = 1dp[2] = 2# 从第3级台阶开始,计算每个台阶的爬法总数for i in range(3, n + 1):# dp[i]是通过从第i-1级台阶爬1步或从第i-2级台阶爬2步到达的dp[i] = dp[i - 1] + dp[i - 2]# 返回爬到第n级台阶的方法总数return dp[n]

四、使用最小花费爬楼梯(Leetcode 746)

1.确定dp数组以及下标的含义:到达第i台阶所花费的最少体力为dp[i]。

2.确定递推公式:

dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。

dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。

那么

dp[i] = min( dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2] )

3.dp数组如何初始化:根据dp数组的定义,到达第0台阶所花费的最小体力为dp[0], 初始化 dp[0] = 0,dp[1] = 0;

4.确定遍历顺序:从前向后遍历

5.举例推导dp数组(debug用):

cost = [ 1, 100, 1, 1, 1, 100, 1, 1, 100, 1]

dp = [0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 6]

class Solution:def minCostClimbingStairs(self, cost: List[int]) -> int:# 创建一个大小为len(cost)+1的dp数组,dp[i]表示到达第i个台阶的最小费用dp = [0] * (len(cost) + 1)# 初始化dp[0]和dp[1],爬到第0个和第1个台阶不需要额外的费用dp[0], dp[1] = 0, 0# 从第2个台阶开始,计算每个台阶到达的最小费用for i in range(2, len(cost) + 1):# dp[i]是从第i-1个台阶或第i-2个台阶跳跃到当前台阶所花的最小费用dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])# 返回到达最后一个或倒数第二个台阶的最小费用return dp[len(cost)]
http://www.xdnf.cn/news/183529.html

相关文章:

  • 每日c/c++题 备战蓝桥杯(P2392 kkksc03考前临时抱佛脚)
  • 若依/RuoYi 内置功能
  • tensor 的连续性 与 contiguous() 方法
  • 全星APQP软件系统:驱动芯片半导体行业研发管理迈向高效与合规新高度
  • 远程通信历史上为什么电话网络从模拟信号转向了数字信号?
  • Super Sample Tasker 学习-1
  • disruptor-spring-boot-start版本优化升级
  • LeetCode 每日一题 2025/4/21-2025/4/27
  • C++初阶-模板初阶
  • 杭电oj(1008、1012、1013、1014、1017)题解
  • 【文心快码】确实有点东西!
  • Redis 通用命令与keyspace
  • element-ui dropdown 组件源码分享
  • QML中的色彩应用
  • 调度算法的模拟及应用
  • 接口测试详解
  • electron-vite 应用打包自定义图标不显示问题
  • 28-29【动手学深度学习】批量归一化 + ResNet
  • Java线程池详解
  • 2024年12月GESP 图形化 一级考级真题——飞行的小猫
  • Linux的例行性工作(crontab)
  • 码蹄杯——tips
  • MAGI-1: Autoregressive Video Generation at Scale
  • 基于Jamba模型的天气预测实战
  • java工具类
  • Redis哨兵模式深度解析:实现高可用与自动故障转移的终极指南
  • 大语言模型架构基础与挑战
  • 简单了解Java的I/O流机制与文件读写操作
  • 智能电网新引擎:动态增容装置如何解锁输电线路潜力?
  • spark学习总结