动态规划(逐级总结)

注:此篇宏观看待动态规划问题(分步解决问题)

日升时奋斗,日落时自省

目录

1、斐波那契数列模型(爬楼梯)

2、路径问题(地下城)

3、简单多状态问题(买卖股票IV)

4、子数组系列(单词拆分)

5、子序列问题(最长等差数列)

6、回文串问题(回文子串)

 7、两个数组的dp问题(最长重复子数组)

8、01背包问题(分割等和子集)

9、完全背包问题(零钱兑换II)


1、斐波那契数列模型(爬楼梯)

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

 圈了这么几个地方,就是想要到最后一个格子的时候需要的最小花费

状态表示:dp[i]表示第i个位置,最小花费 (题上想要啥满足就是)

状态转移方程:

 初始化(最后两个位置):dp[m-1]=cost[m-1];dp[m-2]=cost[m-2];

前者的数据需要的后者来支持,所以这里初始化后面的数据,我们从后面开始动态规划

填表顺序:

从右往左

返回值:min(dp[0],dp[1])   因为我们可能是从0或者1出发的,所以这里取0或者1最小值

代码:

    public int minCostClimbingStairs(int[] cost) {int m=cost.length;int[] dp=new int[m];dp[m-1]=cost[m-1];dp[m-2]=cost[m-2];for(int i=m-3;i>=0;i--){dp[i]=Math.min(dp[i+1],dp[i+2])+cost[i];}return Math.min(dp[0],dp[1]);}

2、路径问题(地下城)

来源力扣:174. 地下城游戏 - 力扣(LeetCode)

状态分析:

 状态表示(明显是一个二维表):

错误分析:dp[i][j]表示从起点出发,到[i][j]位置的时候,所需血量最小

正确分析:dp[i][j]:表示从[i,j]出发,到终点

初始化:

边界初始化,上图已经给了

 填表顺序:

从下往上,从有往左

返回值:dp[0][0]

代码:

    public int calculateMinimumHP(int[][] dungeon) {int n=dungeon.length;int m=dungeon[0].length;int[][] dp=new int[n+1][m+1];for(int i=0;i<m-1;i++){dp[n][i]=Integer.MAX_VALUE;}for(int j=0;j<n-1;j++){dp[j][m]=Integer.MAX_VALUE;}dp[n-1][m]=1;dp[n][m-1]=1;for(int i=n-1;i>=0;i--){for(int j=m-1;j>=0;j--){dp[i][j]=Math.min(dp[i+1][j],dp[i][j+1])-dungeon[i][j];dp[i][j]=Math.max(1,dp[i][j]);}}return dp[0][0];}

3、简单多状态问题(买卖股票IV)

 来源力扣:188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

状态分析:

f[i][j](表示买入状态):  到第i天 ,完成j次交易 

g[i][j](表示卖出状态):到第i天,完成j次交易

状态转移方程:

状态转移:

f[i][j]=max(f[i-1][j],g[i-1][j]-p[i]); 

由两部分构成

一部分前一天啥也不做还是买入状态就是 i-1,次数还是当前次数j;

另一部分前一天卖出次数仍然没有改变(买入态)i-1,次数还是当前次数j;

g[i][j]=max(f[i-1][j-1]+p[i],g[i-1][j]);

由两部分构成

一部分前一天啥也不做还是卖出状态就是 i-1,次数还是当前次数j;

另一部分前一天买入次数改变状态(卖出态)i-1,次数+1,我们需要的是上一次的j-1;

初始化:

 填表顺序:

从上往下,从左往右

返回值:需要找到最后一行的最大值,相当于是最后一天(没有交易,交易1次....交易n次的结果)

代码:

    public int maxProfit(int k, int[] prices) {int n=prices.length;int[][] f=new int[n][k+1];int[][] g=new int[n][k+1];f[0][0]=-prices[0];g[0][0]=0;//初始化for(int i=1;i<3;i++){f[0][i]=-0x3f3f3f;g[0][i]=-0x3f3f3f;}//状态转义for(int i=1;i<n;i++){for(int j=0;j<k+1;j++){f[i][j]=Math.max(f[i-1][j],g[i-1][j]-prices[i]);g[i][j]=g[i-1][j];if(j-1>=0){g[i][j]=Math.max(g[i][j],f[i-1][j-1]+prices[i]);}}}int ret=0;//从最后一行动规中找最大值for(int i=0;i<k+1;i++){ret=Math.max(ret,g[n-1][i]);}return ret;}

4、子数组系列(单词拆分)

 来源力扣:139. 单词拆分 - 力扣(LeetCode)

状态分析:

状态转义方程:

决定dp[i]的就是两部分是否为 true

dp[j-1]&& substring(j,i+1)

但是为了判断方便这里将单词存到hash表中为了判断截取是否包含单词

初始化:

开始的时候dp[0]就是空串,啥也没有同样为真,因为单词序列中也没有 dp[0]=true

填表顺序:

从左往右

返回值:dp[n]

代码:

    public boolean wordBreak(String s, List<String> wordDict) {/** 优化 将字典里面的单词存到哈希表中* */Set<String> hash=new HashSet<>(wordDict);int n=s.length();boolean[] dp=new boolean[n+1];dp[0]=true;s=" "+s;   //加空串是为了动规 不用去处理下标映射问题for(int i=1;i<=n;i++){//第二次for循环没有方向要求, j=1; j<=i ;j++ 也行for(int j=i;j>=1;j--){if(dp[j-1]&&hash.contains(s.substring(j,i+1))){dp[i]=true;break;}}}return dp[n];}

5、子序列问题(最长等差数列)

注:子序列和子数组是不一样的

子序列是不一定连续的子集,子数组是连续的子集

 来源力扣:1027. 最长等差数列 - 力扣(LeetCode)

状态分析:

动态转义方程:

那这么才能知道k下标的数字是不是在数组中,那就把下标和数字关联起来,来一个哈希关联起来

 dp[i][j]=dp[2b-c][i]+1 

然后记录数据

初始化:等差数列至少需要3个的,基本数量为2,a需要b、c才能确定

填表顺序:从前往后,因为第三个数据需要依赖前两个值才能确定找不找到

返回值:统计的个数

代码:

    public int longestArithSeqLength(int[] nums) {Map<Integer,Integer> hash=new HashMap<>();//首先将第一个值hash.put(nums[0],0);int n=nums.length;int[][] dp=new int[n][n];//进行初始化为 个数2for(int i=0;i<n;i++){Arrays.fill(dp[i],2);}int ret=2; //计算个数为2for(int i=1;i<n;i++){   //相当于 b//第二个值从 b位置开始   j的位置相当于cfor(int j=i+1;j<n;j++){//计算 a 的 2b-cint a=2*nums[i]-nums[j];//此时判断 hash 是否包含 a if(hash.containsKey(a)){dp[i][j]=dp[hash.get(a)][i]+1;//计算次数ret=Math.max(dp[i][j],ret);}}//将本次数字添加到hashhash.put(nums[i],i);}return ret;}

6、回文串问题(回文子串)

 来源力扣:647. 回文子串 - 力扣(LeetCode)

状态分析:

状态转义方程:

根据状态分析写

如果s[i]!=s[j] 说明dp[i][j]==false;这个基本不用写

后面三个条件可以直接合成一个三目运算

如果s[i]==s[j]则 dp[i][j]=i+1<j?dp[i+1][j-1]:true

如果i+1<j 说明不是相邻也不是重叠那就需要区间[i+1,j-1]是true

初始化:不用初始化

填表顺序:其实需要看状态分析 中的dp[i][j]可能会依赖到dp[i+1][j-1]

从下往上,从左往右  i表示行  j表示列

返回值:统计有多少个子串,把dp中为true都计数一下

代码:

    public int countSubstrings(String s) {int n=s.length();//创建后默认为false  为false的情况不用处理boolean[][] dp=new boolean[n][n];int ret=0;for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){//只需要相等设置为trueif(s.charAt(i)==s.charAt(j)){dp[i][j]=i+1<j?dp[i+1][j-1]:true;}//如果是true说明本身计数if(dp[i][j]==true){ret++;}}}return ret;}

注:为啥第二次for循环从i开始 因为j等于>=i所以j从i开始

 7、两个数组的dp问题(最长重复子数组)

力扣来源:718. 最长重复子数组 - 力扣(LeetCode)

状态分析:

 状态转义方程:

如果两个数组数值相同的话

不等的情况下就不用处理了,相等的话满足动规dp[i][j]=dp[i-1][j-1]+1

初始化:

填表顺序:

从上往下,从左往右

返回值:统计的个数

代码:

    public int findLength(int[] nums1, int[] nums2) {int m=nums1.length;int n=nums2.length;int[][] dp=new int[m+1][n+1];//计数器int ret=0;for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){//如果两个值相等的话if(nums1[i-1]==nums2[j-1]){//相当于个数加一dp[i][j]=dp[i-1][j-1]+1;//求取最大长度ret=Math.max(ret,dp[i][j]);}}}return ret;}

8、01背包问题(分割等和子集)

01背包问题:就是满足于

牛客来源:416. 分割等和子集 - 力扣(LeetCode)

状态分析:

状态转义方程:

初始化:看见 dp[i-1][j-num[i]],需要依赖上一行,所以需要一个扩展行

填表顺序:

从左往右,从上往下

返回值:dp[n][sum/2]

代码:

    public boolean canPartition(int[] nums) {int n=nums.length;int sum=0;//求所有和for(int x:nums)sum+=x;//如果是奇数 就没有相等的情况if(sum%2==1)return false;//求子集的一半int aim=sum/2;//行要多一行  aim 可以不加1 这里只是为了方便理解boolean[][] dp=new boolean[n+1][aim+1];//一行所有的值 为 truefor(int i=0;i<=n;i++){dp[i][0]=true;}for(int i=1;i<=n;i++){//从 i 开始  避开开始的位置for(int j=1;j<=aim;j++){//不选择 第i个位置 dp[i][j]=dp[i-1][j];//选择第i个位置 需要条件的 当前值 大于 数值if(j>=nums[i-1]){//选i 和 不选i 的情况 只要能构成就可以子集一半就行dp[i][j]=dp[i][j]||dp[i-1][j-nums[i-1]];}}}return dp[n][aim];}

 优化:

 代码:

简单点说:直接把行都删了就行  (这里算是优化版的优化,直接让数组从大于nums[i-1]的位置开始的就不用判断j>nums[i-1])

    public boolean canPartition(int[] nums) {int n=nums.length;int sum=0;for(int x:nums)sum+=x;if(sum%2==1)return false;int aim=sum/2;boolean[] dp=new boolean[aim+1];dp[0]=true;for(int i=1;i<=n;i++){for(int j=aim;j>=nums[i-1];j--){dp[j]=dp[j]||dp[j-nums[i-1]];}}return dp[aim];}

9、完全背包问题(零钱兑换II)

力扣来源:518. 零钱兑换 II - 力扣(LeetCode)

状态分析:

 状态转义方程:

但是 能不能选 i 是需要满足条件的  满足条件就是 j-n*coins>=0 就能满足

初始化:

填表顺序:从左往右,从上往下

返回值: dp[n][amount]

代码:

    public int change(int amount, int[] coins) {int n=coins.length;int[][] dp=new int[n+1][amount+1];//设置第一个值 为 1dp[0][0]=1;for(int i=1;i<=n;i++){//从 0 开始 for(int j=0;j<=amount;j++){//不选 idp[i][j]=dp[i-1][j];//选 i 的时候 就需要 j>=coins 才能加上if(j>=coins[i-1]){dp[i][j]+=dp[i][j-coins[i-1]];}}}return dp[n][amount];}

空间优化: 

简单点说,去掉行,填表顺序是从左往右

代码:

    public int change(int amount, int[] coins) {int n=coins.length;int[] dp=new int[amount+1];dp[0]=1;for(int i=1;i<=n;i++){for(int j=coins[i-1];j<=amount;j++){dp[j]+=dp[j-coins[i-1]];}}return dp[amount];}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《WebKit 技术内幕》之八(3):硬件加速机制

3 其他硬件加速模块 3.1 2D图形的硬件加速机制 其实网页中有很多绘图操作是针对2D图形的&#xff0c;这些操作包括通常的网页绘制&#xff0c;例如绘制边框、文字、图片、填充等&#xff0c;它们都是典型的2D绘图操作。在HTML5中&#xff0c;规范又引入了2D绘图的画布功能&a…

常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)

前言 有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法&#xff0c;观察者模式&#xff0c;策略模式) 工程方法 定义 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。 ——《设…

服务端实现微信小游戏登录

1 微信小程序用户登录及其流程 小程序可以通过微信官方提供的登录能力,便能方便的获取微信提供的用户身份标识,达到建立用户体系的作用。 官方文档提供了登录流程时序图,如下: 从上述的登录流程时序图中我们发现,这里总共涉及到三个概念。 第一个是小程序,小程序即我们…

【征服redis15】分布式锁的功能与整体设计方案

目录 1. 分布式锁的概念 2.基于数据库做分布式锁 2.1 基于表主键唯一做分布式锁 2.2 基于表字段版本号做分布式锁 2.3 基于数据库排他锁做分布式锁 3.使用Redis做分布式锁 3.1 redis实现分布式锁的基本原理 3.2 问题一&#xff1a;增加超时机制&#xff0c;防止长期持有…

【Python从入门到进阶】47、Scrapy Shell的了解与应用

接上篇《46、58同城Scrapy项目案例介绍》 上一篇我们学习了58同城的Scrapy项目案例&#xff0c;并结合实际再次了项目结构以及代码逻辑的用法。本篇我们来学习Scrapy的一个终端命令行工具Scrapy Shell&#xff0c;并了解它是如何帮助我们更好的调试爬虫程序的。 一、Scrapy Sh…

Java实现大学计算机课程管理平台 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

第一篇【传奇开心果系列】beeware的toga开发移动应用:轮盘抽奖移动应用

系列博文目录 beeware的toga开发移动应用示例系列博文目录一、项目目标二、开发传奇开心果轮盘抽奖安卓应用编程思路三、传奇开心果轮盘抽奖安卓应用示例代码四、补充抽奖逻辑实现五、开发传奇开心果轮盘抽奖苹果手机应用编程思路六、开发传奇开心果轮盘抽奖苹果手机应用示例代…

【 CSS 】基础 2

“生活就像骑自行车&#xff0c;想要保持平衡&#xff0c;就得不断前行。” - 阿尔伯特爱因斯坦 CSS 基础 2 1. emmet 语法 1.1 简介 Emmet语法的前身是 Zen coding&#xff0c;它使用缩写&#xff0c;来提高 HTML / CSS 的编写速度&#xff0c; VSCode 内部已经集成该语法。…

webpack-dev-server原理解析及其中跨域解决方法

webpack proxy ,就是 webpack 提供的解决跨域的方案。其基本行为是接受客户端发送的请求后转发给其他的服务器&#xff0c;目的是为了解决在开发模式下的跨域问题。 原理 webpack中的proxy 工作原理是利用了 http-proxy-middleware 这个http 代理中间件&#xff0c;实现将请求…

专门为机器学习开发的jpy语言

这本来是一个为工科教学专门开发的附属品&#xff0c;并不是说Python或Java有多不好&#xff0c;根本上它就是一个Java工程教材&#xff0c;但又要结合人工智能。因此&#xff0c;出现了这样一个包容性的怪胎&#xff0c;可以用python一样的语法与Java一起编写。 没流行起来的一…

<信息安全>《2 国内主要企业网络安全公司概览(二)》

4 北京天融信科技有限公司(简称天融信) 信息内容LOGO成立日期创始于1995年总部北京市海淀区上地东路1号院3号楼北侧301室背景民营企业是否上市天融信[002212]A股市值99亿主要产品网络安全大数据云服务员工规模6000多人简介天融信科技集团&#xff08;证券代码&#xff1a;0022…

【开源】基于JAVA的停车场收费系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 停车位模块2.2 车辆模块2.3 停车收费模块2.4 IC卡模块2.5 IC卡挂失模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 停车场表3.2.2 车辆表3.2.3 停车收费表3.2.4 IC 卡表3.2.5 IC 卡挂失表 四、系统实现五、核心代码…

在达沃斯,人工智能引发的乐观情绪可谓一分为二

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

基于STM32的基础实验(一)

LED实验 采用STM32单片机设计电路&#xff0c;控制LED灯的亮灭&#xff0c;对单片机端口的位操作进行演示。 实验需要&#xff1a; STM32核心板独立LED 电路原理图 LED灯实际上是一个特殊的二极管&#xff0c;通过控制高低电平亮灭。如图所示&#xff0c;当1为低电平&#…

数据可视化 | 期末复习 | 补档

文章目录 &#x1f4da;介绍可视化&#x1f407;什么是可视化&#x1f407;科学可视化&#xff0c;信息可视化&#xff0c;可视分析系统三者之间有什么区别&#x1f525;&#x1f407;可视化的基本流程&#x1f407;可视化的两个基本设计原则&#x1f407;数据属性&#x1f407…

数学建模学习笔记||层次分析法

评价类问题 解决评价类问题首先需要想到一下三个问题 我们评价的目标是什么我们为了达到这个目标有哪几种可行方案评价的准则或者说指标是什么 对于以上三个问题&#xff0c;我们可以根据题目中的背景材料&#xff0c;常识以及网上收集到的参考资料进行结合&#xff0c;从而筛…

GEE:最小距离分类器(minimumDistance)分类教程(样本制作、特征添加、训练、精度、最优参数、统计面积)

作者:CSDN @ _养乐多_ 本文将介绍在Google Earth Engine (GEE)平台上进行最小距离分类(minimumDistance)的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量(各种指数、纹理特征、时间序列特征、物候特征等),运行…

本地git切换地区后,无法使用ssh访问github 22端口解决方案

问题 由于放假回家&#xff0c;发现之前一直使用正常的git&#xff0c;与github无法通讯&#xff0c;pull和push都无法连接。报错如下&#xff1a; connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository. 原因 可能是所…

docker常用基础命令

文章目录 1、Docker 环境信息命令1.1、docker info1.2、docker version 2、系统日志信息常用命令2.1、docker events2.2、docker logs2.3、docker history 3、容器的生命周期管理命令3.1、docker create3.2、docker run 总结 1、Docker 环境信息命令 1.1、docker info 显示 D…

Linux 命令大全 CentOS常用运维命令

文章目录 1、Linux 目录结构2、解释目录3、命令详解3.1、shutdown命令3.1、文件目录管理命令ls 命令cd 命令pwd 命令tree 命令mkdir 命令touch 命令cat 命令cp 命令more 命令less 命令head 命令mv 命令rm 命令ln 命令tail 命令cut命令 3.2、用户管理useradd/userdel 命令用户的…