【七】【C语言\动态规划】最大子数组和、环形子数组的最大和、乘积最大子数组,三道题目深度解析

动态规划

动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利用已经计算好的小问题的解,而不需要重复计算。

动态规划与数学归纳法思想上十分相似。

数学归纳法:

  1. 基础步骤(base case):首先证明命题在最小的基础情况下成立。通常这是一个较简单的情况,可以直接验证命题是否成立。

  2. 归纳步骤(inductive step):假设命题在某个情况下成立,然后证明在下一个情况下也成立。这个证明可以通过推理推断出结论或使用一些已知的规律来得到。

通过反复迭代归纳步骤,我们可以推导出命题在所有情况下成立的结论。

动态规划:

  1. 状态表示:

  2. 状态转移方程:

  3. 初始化:

  4. 填表顺序:

  5. 返回值:

数学归纳法的基础步骤相当于动态规划中初始化步骤。

数学归纳法的归纳步骤相当于动态规划中推导状态转移方程。

动态规划的思想和数学归纳法思想类似。

在动态规划中,首先得到状态在最小的基础情况下的值,然后通过状态转移方程,得到下一个状态的值,反复迭代,最终得到我们期望的状态下的值。

接下来我们通过三道例题,深入理解动态规划思想,以及实现动态规划的具体步骤。

53. 最大子数组和

题目解析

动态表示

动态表示一般是通过经验+题目得到的。

经验一般是指,以某个位置为结尾,或者以某个位置为开始。

我们可以定义dp[i]表示以下标i为结尾的子数组,所能得到的最大和。

因为所有的子数组都有一个结尾,结尾的元素一定是nums数组的某一个元素。

所以我们可以用这个标准划分状态。

动态转移方程

我们想一想dp[i]的状态能不能由其他的状态推导得出?

dp[i]表示以下标i为结尾的子数组,所能得到的最大和。

dp[i-1]表示以下标i-1为结尾的子数组,所能得到的最大和。

对于以下标i为结尾的子数组,要么该子数组只有下标i一个元素,要么不止i下标一个元素。

如果只有下标i一个元素,那么dp[i]=nums[i]

如果不止下标i一个元素,那么dp[i]=dp[i-1]+nums[i]

因为dp[i]表示的是所能获得的最大和,所以在这两种情况中,我们需要选其中的更大的值。

故状态转移方程为,dp[i]=max(nums[i],dp[i-1]+nums[i])

初始化

根据状态转移方程,我们知道,想要推导出dp[i]需要用到dp[i-1]。

所以我们需要初始化第一个位置的状态,即初始化dp[0]。

dp[0]表示以下标0为结尾的子数组,所能得到的最大和。

很容易得到,dp[0]=nums[0]。

填表顺序

根据状态转移方程,我们知道,想要推导出dp[i]需要用到dp[i-1]。

所以我们应该从左往右填写dp表。

返回值

我们需要得到所有子数组中,最大的连续和,所以我们需要遍历所有情况,记录最大值。

代码实现

 
int maxSubArray(int* nums, int numsSize) {//dp[i]表示以下标i结尾的连续子数组所能得到的最大和int n=numsSize;int dp[n];int ret=nums[0];dp[0]=nums[0];for(int i=1;i<n;i++){dp[i]=fmax(nums[i],dp[i-1]+nums[i]);ret=fmax(dp[i],ret);}return ret;
}

我们可以在填表的时候,每填写一个状态就比较一次,如果比最大值大就记录。

最后返回ret就是最大和。

918. 环形子数组的最大和

题目解析

动态表示

动态表示是由经验+题目意思得到的。

经验一般是以某个位置为结尾,或者以某个位置为开始。

根据题目分析,我们需要记录最大和和最小和。

所以我们应该定义f[i]、g[i],分别表示以i下标为结尾的子数组所能得到的最大和、最小和。

即,f[i]表示以i下标为结尾的子数组所能得到的最大和。

g[i]表示以i下标为结尾的子数组所能得到的最小和。

动态转移方程

我们想一想能不能由其他状态推导出f[i],g[i]?

f[i]表示以i下标为结尾的子数组所能得到的最大和。

g[i]表示以i下标为结尾的子数组所能得到的最小和。

f[i-1]表示以i-1下标为结尾的子数组所能得到的最大和。

g[i-1]表示以i-1下标为结尾的子数组所能得到的最小和。

对于f[i],以i下标为结尾的子数组,分两种情况,第一种情况是这个子数组只有i下标一个元素,第二种情况是不止i下标一个元素。

如果只有i下标一个元素,所能得到的最大和就是nums[i]本身。

如果不止i下标一个元素,所能得到的最大和就是f[i-1]+nums[i]。

所以f[i]=max(nums[i],f[i-1]+nums[i])

同理,g[i]=min(nums[i],g[i-1]+nums[i])

初始化

根据动态转移方程,我们知道想要推导出i下标状态需要用到i-1位置的状态。

所以我们需要初始化第一个位置的状态。

即,f[0]=nums[0],g[0]=nums[0]

填表顺序

根据状态转移方程,我们知道想要推导出i下标状态需要用到i-1位置的状态。

所以我们应该从左往右开始填写。

返回值

我们应该返回两种情况下的最大和。

要么最大和对应子数组在nums数组中间,要么最大和对应子数组在nums数组首尾。

当最大和对应子数组在nums数组中间时,我们只需要一个变量记录f[i]中的最大值即可

当最大和对应子数组在nums数组首尾时,我们需要一个变量记录g[i]中的最小值,然后还需要判断min是不是等于sum,如果是相等的,sum-min就没有意义。如果不相等,sum-min就是首尾情况的最大和。

返回这两种情况的最大和即可。

代码实现

 
int maxSubarraySumCircular(int* nums, int numsSize) {int n=numsSize;int sum=0;for(int i=0;i<n;i++){sum+=nums[i];}int f[n];int g[n];//f:最大和//g:最小和int max=nums[0],min=nums[0];f[0]=nums[0];g[0]=nums[0];for(int i=1;i<n;i++){f[i]=fmax(nums[i],f[i-1]+nums[i]);g[i]=fmin(nums[i],g[i-1]+nums[i]);max=fmax(max,f[i]);min=fmin(min,g[i]);}return sum==min?max:fmax(sum-min,max);}

152. 乘积最大子数组

题目解析

动态表示

动态表示是由经验+题目意思得到的。

经验一般是以某个位置为结尾,或者以某个位置为开始。

根据题目意思我们需要求最大乘积值。

所以我们可以定义dp[i]表示以i下标结尾的子数组所能得到的最大乘积值。

(修正动态表示,f[i]表示以i下标结尾的子数组所能得到的最大乘积值

g[i]表示以i下标结尾的子数组所能得到的最小乘积值)

动态转移方程

我们想一想dp[i]能不能由其他状态推导得出?

dp[i]表示以i下标结尾的子数组所能得到的最大乘积值。

dp[i-1]表示以i-1下标结尾的子数组所能得到的最大乘积值。

(正数乘以最大值就是最大值,正数乘以最小值就是最小值)

(负数乘以最大值就是最小值,负数乘以最小值就是最大值)

对于dp[i],如果nums[i]>0,dp[i]=dp[i-1]*nums[i]

如果nums[i]<0,dp[i]=(i-1位置的最小乘积值)*nums[i]

所以我们发现只存储最大乘积值是不够的。所以我们修正动态表示。

(修正动态表示,f[i]表示以i下标结尾的子数组所能得到的最大乘积值

g[i]表示以i下标结尾的子数组所能得到的最小乘积值)

对于f[i],如果nums[i]>0,f[i]=f[i-1]*nums[i]

如果nums[i]<0,f[i]=g[i-1]*nums[i]

如果nums[i]=0,f[i]=0

对于g[i],如果nums[i]>0,g[i]=g[i-1]*nums[i]

如果nums[i]<0,g[i]=f[i-1]*nums[i]

如果nums[i]=0,f[i]=0

如果nums[i]=0,是可以把这种情况归类于nums[i]<0这种情况或者nums[i]>0这种情况中,因为当nums[i]=0,

f[i]=f[i-1]*nums[i]

f[i]=g[i-1]*nums[i]

g[i]=g[i-1]*nums[i]

g[i]=f[i-1]*nums[i]

都是等于0,所以动态转移方程可以写为

int x=nums[i]; int y=nums[i]*f[i-1]; int z=nums[i]*g[i-1]; f[i]=fmax(x,fmax(y,z)); g[i]=fmin(x,fmin(y,z));

初始化

根据动态转移方程,我们知道想要推导i位置的状态,需要i-1位置的状态,所以我们需要初始化第一个位置的状态。

即, f[0]=nums[0]; g[0]=nums[0];

填表顺序

根据状态转移方程,我们知道想要推导i位置的状态,需要i-1位置的状态,所以我们应该从左往右开始填写,同时填写两个表格。

返回值

f[i]表示以i下标结尾的子数组所能得到的最大乘积值

g[i]表示以i下标结尾的子数组所能得到的最小乘积值

我们要求的是最大乘积值,所以需要遍历f[i]数组中所有的值,找出最大值。

代码实现

 
int maxProduct(int* nums, int numsSize) {int n=numsSize;int f[n];int g[n];f[0]=nums[0];g[0]=nums[0];int ret=nums[0];for(int i=1;i<n;i++){int x=nums[i];int y=nums[i]*f[i-1];int z=nums[i]*g[i-1];f[i]=fmax(x,fmax(y,z));g[i]=fmin(x,fmin(y,z));ret=fmax(ret,f[i]);}return ret;
}

结尾

今天我们学习了动态规划的思想,动态规划思想和数学归纳法思想有一些类似,动态规划在模拟数学归纳法的过程,已知一个最简单的基础解,通过得到前项与后项的推导关系,由这个最简单的基础解,我们可以一步一步推导出我们希望得到的那个解,把我们得到的解依次存放在dp数组中,dp数组中对应的状态,就像是数列里面的每一项。最后感谢您阅读我的文章,对于动态规划系列,我会一直更新,如果您觉得内容有帮助,可以点赞加关注,以快速阅读最新文章。

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

python脚本抢各大平台大额优惠卷

文章目录 python脚本抢各大平台大额优惠卷写在前面准备阶段一、所需工具二、ChromeDriver下载教程 三、Seleuinm安装1、打开cmd&#xff0c;输入如下命令 开始抢券淘宝脚本京东抢购脚本 python脚本抢各大平台大额优惠卷 写在前面 当电商平台上演盛大的购物狂欢时&#xff0c;如…

SpringBoot3 基础特性

1. SpringApplication 1.1. 自定义 banner 类路径添加banner.txt或设置spring.banner.location就可以定制 banner推荐网站&#xff1a;Spring Boot banner 在线生成工具&#xff0c;制作下载英文 banner.txt&#xff0c;修改替换 banner.txt 文字实现自定义&#xff0c;个性化…

数据驱动与数据安全,自动驾驶看得见的门槛和看不见的天花板

作者 |田水 编辑 |德新 尽管心理有所准备&#xff0c;2023年智能驾驶赛道的内卷程度还是超出了大多数人的预期。 这一年&#xff0c;汽车价格战突然开打&#xff0c;主机厂将来自销售终端的价格压力&#xff0c;传导到下游智驾供应商&#xff0c;于是&#xff0c;市面上出现…

医院云HIS系统源码,saas多医院版,适用于专科医院、集团医院、基层医院

医院云HIS系统源码&#xff0c;自主研发&#xff0c;自主版权&#xff0c;电子病历病历4级 系统概述&#xff1a; 一款满足基层医院各类业务需要的云HIS系统。该系统能帮助基层医院完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统…

数据结构:单调栈

1.单调栈 单调栈是一种数据结构&#xff0c;其中存放的数据应该是有序的&#xff0c;所以单调栈也有单调递减栈和单调递增栈 单调递增栈&#xff1a;栈顶到栈底的元素大小是从小到大 单调递减栈&#xff1a;栈顶到栈底的元素大小是从大到小 单调栈主要就是用来求一个给定序列中…

【unity3D-粒子系统】粒子系统主模块-Particle System篇

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的粒子系统主模块-Particle System 基础知识 Particle System 介绍&#xff1a;粒子系统的主模块&#xff0c;是必需的模块&#x…

ESP8266 ESP-01/01s 工作模式与固件下载烧录接线

注意点&#xff1a; ESP8266 ESP-01与 ESP8266 ESP-01s接线类似 。本文使用的是ESP8266 ESP-01 WIFI模块&#xff0c;详细信息见如下图片。本文固件下载的是ESP8266 的MQTT固件&#xff0c;下载其它固件流程一致。本文使用的是杜邦线连接面包板来进行使用&#xff0c;与使用开发…

DRF从入门到精通五(路由组件、认证组件、权限组件、频率组件及认证、权限源码分析)

文章目录 一、路由组件REST framework提供了两个routeraction装饰器 二、认证组件(Authentication)三、权限组件(Permissions)内置权限类 四、频率组件(Throttling)五、权限组件源码分析六、认证组件源码分析 一、路由组件 对于视图集ViewSetMixin&#xff0c;我们除了可以自己…

YOLOv8可视化:引入多种可视化CAM方法,为科研保驾护航

💡💡💡本文内容:调用pytorch下的CAM可视化库,支持十多种可视化方法,打开“黑盒”,让YOLOv8变得相对可解释性 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.html?spm=1001.2014.3001.5482 💡💡💡全网独家首发创新(原创),适…

Vue Echarts 多折线图只有一条X轴(合并X轴数据并去重排序) - 附完整示例

echarts&#xff1a;一个基于 JavaScript 的开源可视化图表库。 目录 效果 一、介绍 1、官方文档&#xff1a;Apache ECharts 2、官方示例 二、准备工作 1、安装依赖包 2、示例版本 三、使用步骤 1、在单页面引入 echarts 2、指定容器并设置容器宽高 3、数据处理&am…

经验分享:构建知识库管理系统只需要这几步

导语&#xff1a; 在当今信息爆炸的时代&#xff0c;构建一个高效的知识库管理系统对于企业来说至关重要。一个好的知识库管理系统可以帮助企业集中管理和共享知识和信息&#xff0c;提高团队的协作效率和创新能力。本文将分享构建知识库管理系统的几个关键步骤&#xff0c;帮…

[Linux] MySQL数据库的备份与恢复

一、数据库备份的分类和备份策略 1.1 数据库备份的分类 1&#xff09;物理备份 物理备份&#xff1a;对数据库操作系统的物理文件&#xff08;如数据文件、日志文件等&#xff09;的备份。 物理备份方法&#xff1a; 冷备份(脱机备份) &#xff1a;是在关闭数据库的时候进…

3D视觉方案的优势

随着机器视觉在工业领域的应用逐渐深入&#xff0c;传统的 2D 视觉方案已经趋向成熟&#xff0c;应用局限性也已经显现出来。 2D 视觉方案易受照明条件影响&#xff0c;一致性和稳定性难以保证&#xff0c;且无法实现三维高精度测量和定位&#xff0c; 3D 视觉方案应运而生&…

奇富科技跻身国际AI学术顶级会议ICASSP 2024,AI智能感知能力迈入新纪元

近日&#xff0c;2024年IEEE声学、语音与信号处理国际会议ICASSP 2024&#xff08;2024 IEEE International Conference on Acoustics, Speech, and Signal Processing&#xff09;宣布录用奇富科技关于语音情感计算的最新研究成果论文“MS-SENet: Enhancing Speech Emotion Re…

如何发送大型文件 ---- 分卷压缩

不知道各位小伙伴有没有这样的烦恼&#xff0c;发送很大很大的压缩包会受到限制&#xff0c;比如QQ邮箱需要付费来进行中转的扩容&#xff0c;下面我将会介绍一种分卷压缩的方法来传送较大的压缩包给对方 使用7-zip软件进行分卷压缩 如果有7-zip压缩软件直接跳过这一步 7-zi…

利用Milvus Cloud和LangChain构建机器人:一种引人入胜且通俗易懂的方法

一、引言 机器人已经深入我们的日常生活&#xff0c;从家庭服务到工业生产&#xff0c;再到医疗和运输等领域。然而&#xff0c;这些机器人往往需要复杂的算法和数据处理技术才能有效地执行任务。在这个过程中&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#…

Spring Boot快速搭建一个简易商城项目【一展示商城首页篇】

前言&#xff1a;今天我来使用Spring Boot快速搭建一个简易商城项目以下是相关的思路流程&#xff0c;如果有更好的思路&#xff0c;欢迎大佬评论留言&#xff01;&#xff01;&#xff01; 一&#xff0c;实现思路&#xff1a; 创建 Spring Boot 项目&#xff1a; 使用 Spring…

Hikvision SPON IP网络对讲广播系统存在命令执行漏洞CVE-2023-6895 附POC软件

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. Hikvision SPON IP网络对讲广播系统简介 微信公众…

理解文件系统

一 什么是文件系统 文件系统是计算机操作系统中的一个核心组件&#xff0c;用于管理计算机中的文件和文件夹。它提供了一种组织和访问计算机存储设备上数据的方式。文件系统使用户能够创建、修改、删除和查找文件&#xff0c;以及组织文件和文件夹的层次结构。 ps: linux一共有…

【FPGA】高云FPGA之科学的FPGA开发流程

FPGA开发流程 开发流程1、设计定义2、设计输入3、分析和综合4、功能仿真5、布局布线6、时序仿真7、IO分配以及配置文件&#xff08;bit流文件&#xff09;的生成8、配置&#xff08;烧录&#xff09;FPGA9、在线调试 例子1、设计定义1.1 需求1.2 原理图1.3 真值表 2、设计输入2…