动态规划算法专题(一):斐波那契数列模型
目录
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视频汇聚融合平台,凭借其强大的数据整合、智能分析与远程监控能力,在城市感知系统中扮…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
