动态规划算法专题(一):斐波那契数列模型
目录
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视频汇聚融合平台,凭借其强大的数据整合、智能分析与远程监控能力,在城市感知系统中扮…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...