动态规划算法专题(一):斐波那契数列模型
目录
1、动态规划简介
2、算法实战应用【leetcode】
2.1 题一:第N个泰波那契数
2.1.1 算法原理
2.1.2 算法代码
2.1.3 空间优化原理——滚动数组
2.1.4 算法代码——空间优化版本
2.2 题二:三步问题
2.2.1 算法原理
2.2.2 算法代码
2.3 题二:使用最小花费爬楼梯
2.3.1 算法原理【解法一】
2.3.2 算法代码【解法一】
2.3.3 算法原理【解法二】
2.3.4 算法代码【解法二】
2.4 题三:解码方法
2.4.1 算法原理
2.4.2 算法代码
2.4.3 初始化技巧
2.4.4 算法代码——初始化技巧使用
1、动态规划简介
动态规划(Dynamic Programming, DP)是运筹学的一个分支,用于求解最优化问题。
在解决问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法(自底向上)正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。
动态规划算法,一般包含以下几个主要步骤:
- 状态表示:dp表中的值所表示的含义。一般由 经验+题目要求 得出。对于一维的dp表,dp[i]通常有这两种表示形式(由经验得出):①:以i位置为结尾,......;②:以i位置为起点,......;而....就是需要结合题目来得出的。
- 状态转移方程:就是dp[i]是怎么来的。dp[i]通常由其相邻的其他状态经过公式计算得出,状态转移方程就是这个公式。
- 初始化:确保在填dp表的过程中不越界。
- 填表顺序:为了在填写当前状态的时候,所需要的其他相邻状态已经计算得出了。
- 返回值:结合题目要求。
在此过程中,我认为确定状态表示是最重要的一点,而确定状态转移方程是最难的一点。
2、算法实战应用【leetcode】
2.1 题一:第N个泰波那契数
. - 力扣(LeetCode)
2.1.1 算法原理
对于一维dp,状态表示通常由 经验+题目要求 得出,本题很明显,表示第i个泰波那契数的值;同时状态转移方程题目也是贴心的给出了。
- 状态表示dp[i]:第i个泰波那契数的值
- 状态转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
- 初始化:dp[0] = 0; dp[1] = dp[2] = 1;
- 填表顺序:从左往右
- 返回值:dp[n]
2.1.2 算法代码
class Solution {public int tribonacci(int n) {if(n == 0) return 0;if(n == 1 || n == 2) return 1;int[] dp = new int[n + 1];dp[0] = 0; dp[1] = dp[2] = 1;for(int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];}return dp[n];}
}
2.1.3 空间优化原理——滚动数组
实际上,我们可以不用创建一个dp数组来存储数值,
通过“滚动数组”的方式,进行空间优化。
仅仅使用三个变量就可以解题,不必再开辟额外的空间。
2.1.4 算法代码——空间优化版本
class Solution {public int tribonacci(int n) {//动态规划 -> 空间优化if(n == 0) return 0;if(n == 1 || n == 2) return 1;int a = 0, b = 1, c = 1, d = 0;for(int i = 3; i <= n; i++) {d = a + b + c;//滚动操作a = b;b = c;c = d;}return d;}
}
2.2 题二:三步问题
. - 力扣(LeetCode)
2.2.1 算法原理
- 状态表示(经验+题目要求):dp[i]:到达第i个位置,一共有多少种方式
- 状态转移方程:要到达i位置,可由移动到i-1/i-2/i-3位置的基础上,再移动三/二/一步就可到达,即:dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
- 初始化:dp[1]=1; dp[2]=2; dp[3]=4;
- 填表顺序:从左往右
2.2.2 算法代码
class Solution {//dp[i]状态表示:到达i位置,一共有多少种方法public int waysToStep(int n) {//1e9 + 7:double类型int MOD = (int)1e9 + 7;if(n == 1 || n == 2) return n;int[] dp = new int[n + 1];//初始化dp[1] = 1; dp[2] = 2; dp[3] = 4;for(int i = 4; i < n + 1; i++) {//状态转移方程dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;}return dp[n];}
}
2.3 题二:使用最小花费爬楼梯
. - 力扣(LeetCode)
2.3.1 算法原理【解法一】
- 状态表示dp[i]:到达i位置,最小花费的金额(以i位置为结尾)
- 状态转移方程:需要考虑,到达i-1位置和到达i-2位置最小花费的金额数,考虑完后,再进一步到达i位置。也就是说:dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
- 初始化:dp[0]=0; dp[1]=0;(防越界)
- dp的建表顺序:从左至右
- 返回值:dp[n]
2.3.2 算法代码【解法一】
class Solution {public int minCostClimbingStairs(int[] cost) {//解法一:int n = cost.length;//状态表示dp[i]:到达i位置时,最小花费int[] dp = new int[n + 1];//初始化dp[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]);}//返回值:dp[n]return dp[n];}
}
2.3.3 算法原理【解法二】
- 状态表示dp[i]:从i位置开始,到达楼顶,最小花费的金额(以i位置为起点)
- 状态转移方程:需要考虑,i+1位置和i+2位置到达楼顶最小花费的金额数,再选择走一步还是走两步。也就是说:dp[i]=min(cost[i-1],dp[i-2])+cost[i];
- 初始化:dp[i-1]=cost[i-1]; dp[i-2]=cost[i-2];(防越界)
- dp的建表顺序:从右至左
- 返回值:min(dp[0],dp[1])
2.3.4 算法代码【解法二】
class Solution {public int minCostClimbingStairs(int[] cost) {int n = cost.length;//状态表示dp[i]:以i位置为起点,到达楼顶的最小花费int[] dp = new int[n];//初始化dp[n - 1] = cost[n - 1];dp[n - 2] = cost[n - 2];for(int i = n - 3; i >= 0; i--) {//填表顺序 -> 从右往左//状态转移方程 --> 自身花费+后面俩台阶的最小花费dp[i] = cost[i] +Math.min(dp[i + 1], dp[i + 2]);}//返回值,考虑 从第一个台阶出发 or 从第二个台阶出发return Math.min(dp[0], dp[1]);}
}
2.4 题三:解码方法
. - 力扣(LeetCode)
2.4.1 算法原理
- 状态表示dp[i]:以i位置为结尾,解码方式的总数
- 状态转移方程:s[i]单独解码(成功/失败)+s[i]/s[i-1]组合解码(成功/失败):dp[i]=dp[i-1]+dp[i-2];
- 初始化:①:if(s[0]!='0') dp[0]=1; ②:dp[1] -->1. s[1]单独解码 & 2. s[1]与s[0]组合解码
- 返回值:dp[n-1]
2.4.2 算法代码
class Solution {public int numDecodings(String s) {int n = s.length();char[] c = s.toCharArray();//状态表示dp[i]:以i位置为结尾,解码方式的总数int[] dp = new int[n];//初始化第一个位置if(c[0] != '0') dp[0]++;//当长度为1时if(n == 1) return dp[0];//初始化第二个位置if(c[0] != '0' && c[1] != '0') dp[1]++;//单独编码int t = ((c[0] - '0') * 10 + (c[1] - '0'));if(t >= 10 && t <= 26) dp[1]++;//组合编码for(int i = 2; i < n; i++) {//单独编码if(c[i] != '0') dp[i] += dp[i - 1];//组合编码int tt = ((c[i - 1] - '0') * 10 + (c[i] - '0'));if(tt >= 10 && tt <= 26) dp[i] += dp[i - 2];}return dp[n - 1];}
}
2.4.3 初始化技巧
在编写代码时,我们发现了一个问题, 我们在完成初始化工作时,非常的麻烦,初始化的代码占据了大量的篇幅,此时,我们可以使用初始化技巧 ---> dp数组在创建时多开辟一个节点。将初始化时的代码放进循环中(将要初始化的节点与普通节点一概而论),在填dp表的时候完成初始化。
不过,因为多开辟了一个位置,所以在循环填dp表时也需要注意以下问题:
- 与原数组的下标映射关系发生了改变
- 注意虚拟节点的值(多开辟的那一个节点),虚拟节点的值,要保证后面计算得到的结果是正确的。
在本题中,虚拟节点dp[0]的值应该为1;
原因:
当s[1]可与s[0]组合解码时,会这样计算:dp[2]+=d[2-2](s中的i为1,映射到新dp中i为2)
因为能够组合解码,所以虚拟节点dp[0]的值应为1
2.4.4 算法代码——初始化技巧使用
class Solution {public int numDecodings(String s) {//初始化技巧 --> 优化int n = s.length();char[] c = s.toCharArray();//状态表示dp[i + 1]:以i位置为结尾,解码方式的总数int[] dp = new int[n + 1];//处理虚拟节点里的值dp[0] = 1;//初始化第一个位置if(c[0] != '0') dp[1]++;for(int i = 2; i < n + 1; i++) {//单独编码if(c[i - 1] != '0') dp[i] += dp[i - 1];//组合编码int t = ((c[i - 1 - 1] - '0') * 10 + (c[i - 1] - '0'));if(t >= 10 && t <= 26) dp[i] += dp[i - 2];}return dp[n];}
}
END
相关文章:

动态规划算法专题(一):斐波那契数列模型
目录 1、动态规划简介 2、算法实战应用【leetcode】 2.1 题一:第N个泰波那契数 2.1.1 算法原理 2.1.2 算法代码 2.1.3 空间优化原理——滚动数组 2.1.4 算法代码——空间优化版本 2.2 题二:三步问题 2.2.1 算法原理 2.2.2 算法代码 2.3 题二&a…...
H.264编解码工具 - x264
一、简介 x264是一个开源的H.264/AVC视频编码库,它可以将视频数据压缩成H.264格式,并且可以从H.264格式解码出原始视频数据。 x264是以C语言编写的,并且可以在多个平台上使用,包括Windows、Linux和Mac OS等操作系统。 x264具有很高的编码效率和视频质量,它支持多种编码…...

外卖点餐小程序源码系统 单店多门店自助切换 带完整的安装代码包以及搭建部署教程
系统概述 本外卖点餐小程序源码系统旨在帮助餐饮企业和商家快速搭建一个功能完善的在线外卖平台。系统支持单店与多门店的灵活切换,方便商家根据自身业务需求进行管理和运营。同时,系统还提供了丰富的营销工具和数据分析功能,助力商家实现精…...

通过Ideal和gitbash共同实现分支合并
文章目录 背景描述:演示jy_20240704_develop分支同步到jy_dev分支方式一方式二 背景描述: 目前项目里有四个分支,分别是master、jy_20240704_develop、jy_dev、jy_qas。 其中master是主分支,其他三个分支都是根据master来创建的…...
Vue.js 组件开发
Vue.js 是一个渐进式的JavaScript框架,主要用于构建用户界面。它采用了组件化的开发方式,使得前端开发更加高效、灵活且易于维护。组件是Vue.js的核心概念之一,理解和掌握组件的开发,有助于我们高效地构建现代Web应用。 本文将涵…...

【Lcode 随笔】C语言版看了不后悔系列持续更新中。。。
文章目录 题目一:最长回文子串题目描述:示例输入与输出:题目分析:解题思路:示例代码:深入剖析: 题目二:合并K个有序链表题目描述:示例输入与输出:题目分析&am…...

排序--希尔排序
希尔排序介绍 希尔排序核心思想就是:1,分组;2,直接插入排序:越有序越快 希尔排序就是多次利用直接插入排序的一个排序算法. 希尔排序的算法思想:间隔式分组,利用直接插入排序让组内有序,然后缩小分组再次排序,直到组数为1希尔排序的理论基础就是直接插入排序越有序越快; 希尔排…...

【教程】57帧! Mac电脑流畅运行黑神话悟空
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 1、先安装CrossOver。网上有许多和谐版,可自行搜索。(pd虚拟机里运行黑神话估计够呛的) 2、运行CrossOver…...
『大模型笔记』Docker如何清理Build Cache!
Docker如何清理Build Cache! 文章目录 一. docker system df1. 镜像(Images)2. 容器(Containers)3. 本地卷(Local Volumes)4. 构建缓存(Build Cache)5. 总结二. 构建缓存(Build Cache)删除有什么影响1. 镜像构建速度变慢2. 磁盘空间被释放3. 不会影响已构建和运行的…...

如何使用 Python 读取数据量庞大的 excel 文件
使用 pandas.read_excel 读取大文件时,的确会遇到性能瓶颈,特别是对于10万行20列这种规模的 .xlsx 文件,常规的 pandas 方法可能会比较慢。 要提高读取速度,关键是找到更高效的方式处理 Excel 文件,特别是在 Python 的…...

c语言200例 067
大家好,欢迎来到无限大的频道 今天给大家带来的是c语言200例 题目要求: 设计一个共用体类型,使其成员包含多种数据类型,根据不同的数据类型,输出不同的结果 要设计一个共用体(union)类型&…...

RabbitMQ的高级特性-死信队列
死信(dead message) 简单理解就是因为种种原因, ⽆法被消费的信息, 就是死信. 有死信, ⾃然就有死信队列. 当消息在⼀个队列中变成死信之后,它能被重新被发送到另⼀个交换器 中,这个交换器就是DLX( Dead Letter Exchange ), 绑定DLX的队列, 就称为死信队…...

Python 复制PDF中的页面
操作PDF文档时,复制其中的指定页面可以帮助我们从PDF文件中提取特定信息,如文本、图表或数据等,以便在其他文档中使用。复制PDF页面也可以实现在不同文件中提取页面,以创建一个新的综合文档。 本文将介绍如何使用Python 在同一文档…...

Sql Developer日期显示格式设置
默认时间格式显示 设置时间格式:工具->首选项->数据库->NLS->日期格式: DD-MON-RR 修改为: YYYY-MM-DD HH24:MI:SS 设置完格式显示:...

IP地址与智能家居能够碰撞出什么样的火花呢?
感应灯、远程遥控空调,自动感应窗帘——智能家居已经在正逐步走入我们的生活,为我们带来前所未有的便捷与舒适体验。而在这一进程中,IP地址又能够与智能家居碰撞出什么样的火花呢? 一、IP地址:智能家居的连接基石 智…...

人工智能技术在电磁场与微波技术专业的应用
在人工智能与计算电磁学的融合背景下,电磁学的研究和应用正在经历一场革命。计算电磁 学是研究电磁场和电磁波在不同介质中的传播、散射和辐射等问题的学科,它在通信、雷达、无 线能量传输等领域具有广泛的应用。随着人工智能技术的发展,这一…...

The First项目报告:探索Yield Guild Games运行机制与发展潜力
在探索数字娱乐与金融融合的全新疆域中,GameFi(游戏化金融)以其独特的魅力引领了一场前所未有的变革。这一创新概念,最初由MixMarvel的CSO Mary Ma在2019年底乌镇大会的远见卓识中首次提出,它将去中心化金融࿰…...

完成UI界面的绘制
绘制UI 接上文,在Order90Canvas下创建Image子物体,图片资源ui_fish_lv1,设置锚点(CountdownPanelImg同理),命名为LvPanelImg,创建Text子物体,边框宽高各50, ,重名为LvT…...

iot网关是什么?iot网关在工业领域的应用-天拓四方
一、IoT网关的定义 IoT网关,即物联网网关,是物联网(IoT)系统中的重要组成部分。它主要实现感知网络与通信网络,以及不同类型感知网络之间的协议转换,既能够支持广域互联,也能满足局域互联的需求…...

从碎片到整合:EasyCVR平台如何重塑城市感知系统的视频数据生态
随着城市化进程的加速,城市感知系统作为智慧城市的重要组成部分,正逐步成为提升城市管理效率、保障公共安全、优化资源配置的关键手段。EasyCVR视频汇聚融合平台,凭借其强大的数据整合、智能分析与远程监控能力,在城市感知系统中扮…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...
Cursor AI 账号纯净度维护与高效注册指南
Cursor AI 账号纯净度维护与高效注册指南:解决限制问题的实战方案 风车无限免费邮箱系统网页端使用说明|快速获取邮箱|cursor|windsurf|augment 问题背景 在成功解决 Cursor 环境配置问题后,许多开发者仍面临账号纯净度不足导致的限制问题。无论使用 16…...