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

代码随想录Day32:动态规划(斐波那契数、爬楼梯、使用最小花费爬楼梯)

一、理论

什么是动态规划(Dynamic Programming)?如果某一问题有很多重叠子问题,使用动态规划是最有效的。动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的,而且很多讲解动态规划的文章都会讲最优子结构啊和重叠子问题啊这些,这些东西都是教科书的上定义,晦涩难懂而且不实用,知道动规是由前一个状态推导出来的,而贪心是局部直接选最优的,对于刷题来说就够用了

误区:状态转移公式(递推公式)只是一部分,必须掌握根本性的解题步骤。

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

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

二、实战

509斐波那契数

509. 斐波那契数 - 力扣(LeetCode)

  • 确定dp数组(dp table)以及下标的含义dp[i]:第i个斐波那契数值
  • 确定递推公式:dp[i]=dp[i-1]+dp[i-2]
  • dp数组如何初始化根据题目描述,dp[0]=dp[1]=1
  • 确定遍历顺序必须从前向后遍历
  • 举例推导dp数组=打印dp数组:用来debug
package org.example.DP;public class fib509 {public int fib(int n) {//特殊情况if (n <= 1) return n;int[] dp=new int[n+1];dp[0]=0;dp[1]=1;for(int i=2;i<=n;i++){dp[i]=dp[i-1]+dp[i-2];}return dp[n];}
}

70爬楼梯

70. 爬楼梯 - 力扣(LeetCode)

爬到第一层楼梯有一种方法,爬到二层楼梯有两种方法。那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层。所以到第三层楼梯的状态可以由第二层楼梯 和 到第一层楼梯状态推导出来,那么就可以想到动态规划了。

  • 确定dp数组(dp table)以及下标的含义dp[i]:第i个台阶有几种方法
  • 确定递推公式:dp[i]=dp[i-1]+dp[i-2]
  • dp数组如何初始化根据题目描述,dp[2]=2,dp[1]=1,这种定义更容易理解
  • 确定遍历顺序必须从前向后遍历
  • 举例推导dp数组=打印dp数组:用来debug
package org.example.DP;public class climbStairs70 {public int climbStairs(int n) {//特殊情况if (n <= 1) return n;int[] dp=new int[n+1];dp[2]=2;dp[1]=1;for(int i=2;i<=n;i++){dp[i]=dp[i-1]+dp[i-2];}return dp[n];}
}

或者初始为  dp[0]=1;dp[1]=1;也可以,但是不太好理解,这个就是为了得出结果倒退的dp[0]定义。

746使用最小花费爬楼梯

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

  • 确定dp数组(dp table)以及下标的含义dp[i]:到第i个台阶的最小花费
  • 确定递推公式:dp[i]=min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
  • dp数组如何初始化根据题目描述,dp[2]=0,dp[1]=0,相当于 跳到 下标 0 或者 下标 1 是不花费体力的, 从 下标 0 下标1 开始跳就要花费体力了。
  • 确定遍历顺序必须从前向后遍历
  • 举例推导dp数组=打印dp数组:用来debug
package org.example.DP;public class minCostClimbingStairs746 {public int minCostClimbingStairs(int[] cost) {int n = cost.length;int[] dp = new int[n + 1];//从下标为 0 或下标为 1 的台阶开始,支付费用为0dp[0] = 0;dp[1] = 0;// 计算到达每一层台阶的最小费用for (int i = 2; i <= n; i++) {dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[n];}
}
http://www.dtcms.com/a/302239.html

相关文章:

  • 字节跳动开源Coze,开启AI Agent开发新时代?
  • 我从 Web2 转型到 Web3 的 9 条经验总结
  • linux命令grep的实际应用
  • Leetcode——11. 盛最多水的容器
  • kubectl中的yaml配置详解
  • 前段面试题新版
  • 从fork到exit:剖析Linux进程的诞生、消亡机制
  • 零基础部署网站?使用天翼云服务搭建语音听写应用系统
  • C++ list 容器全解析:从构造到模拟实现的深度探索----《Hello C++ Wrold!》(16)--(C/C++)
  • [机缘参悟-237]:AI人工神经网络与人类的神经网络工作原理的相似性
  • 嵌入式学习(40)-基于STM32F407Hal库的串口DMA空闲中断接收+DMA发送
  • 前端实现银河粒子流动特效的技术原理与实践
  • 物联网与数字孪生:深度协同驱动智能未来 —— 专业规划分析
  • 解析分区、挂载与块设备:Linux 存储管理核心命令详解
  • 关于前端的性能优化
  • Vue 工程化
  • 初识 docker [下] 项目部署
  • 【案例总结】幽灵单据——消失的交货单号
  • 数据库简介
  • layui-vue 入驻 GitCode 平台:让前端开发更简单优雅
  • 【Oracle】ORACLE-ASM安装
  • vue-grid-layout元素交换位置及大小
  • Python Pandas.merge函数解析与实战教程
  • 【数学建模论文学习笔记】基于历史数据的蔬菜类商品定价与补货决策模型
  • Java从入门到精通!第十八天(JDK17安装以及网络编程) 完结篇!!!
  • 7.29 技巧|
  • 【数据库】使用Sql Server将分组后指定字段的行数据转为一个字段显示,并且以逗号隔开每个值,收藏不迷路
  • C# 接口(interface 定义接口的关键字)
  • JVM 垃圾回收机制全景解析:从对象回收到收集算法
  • Spring Boot日志开发实战手册:集成/输出/级别控制/持久化精要