算法沉淀——动态规划篇(子数组系列问题(上))
算法沉淀——动态规划篇(子数组系列问题(上))
- 前言
- 一、最大子数组和
- 二、环形子数组的最大和
- 三、乘积最大子数组
- 四、乘积为正数的最长子数组长度
前言
几乎所有的动态规划问题大致可分为以下5个步骤,后续所有问题分析都将基于此
-
1.、状态表示:通常状态表示分为基本分为以下两种,其中更是以第一种为甚。
以i为结尾
,dp[i] 表示什么,通常为代求问题(具体依题目而定)以i为开始
,dp[i]表示什么,通常为代求问题(具体依题目而定)
-
2、状态转移方程
*以上述的dp[i]意义为以i位置为分界, 通过最近一步来分析和划分问题
,由此来得到一个有关dp[i]的状态转移方程。 -
3、dp表创建,初始化
- 动态规划问题中,如果直接使用状态转移方程通常会伴随着
越界访问
等风险,所以一般需要初始化。而初始化最重要的两个注意事项便是:保证后续结果正确,不受初始值影响;下标的映射关系
。 - 而
初始化一般分为以下两种:
直接初始化开头的几个值。
一维空间大小+1,下标从1开始;二维增加一行/一列
。
- 动态规划问题中,如果直接使用状态转移方程通常会伴随着
-
4、填dp表、填表顺序:根据状态转移方程来确定填表顺序。
-
5、确定返回值
一、最大子数组和
【题目链接】:53. 最大子数组和
【题目】:
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
&emdp;子数组是数组中的一个连续部分。
【示例】:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
【分析】:
我们可以定义dp[i]表示以i为结尾,最大连续子数组和。此时连续子数组长度分为1和大于1,分别对应如下情况:
- 如果dp[i-1]大于0,此时最大连续子数组和为dp[i-1] + nums[i]。长度大于1。
- 如果dp[i-1] <= 0,此时最大的连续子数组和就是nums[i]本身。长度为1.
所以我们可以得到状态转移方程为:dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1])
。
但显然当i为0时,状态转移方程不适用。这里我们给出的方法时dp表空间额外增加1。同时为了保证在使用状态转移方程,新增空间对后续填表结果不产生印象。我们将dp[0]初始化为0即可。
【代码编写】:
class Solution {
public:int maxSubArray(vector<int>& nums) {int n = nums.size();vector<int> dp(n + 1);int ret = INT_MIN;for(int i = 1; i <= n; i++){dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1]);ret = max(ret, dp[i]);}return ret;}
};
二、环形子数组的最大和
【题目链接】:918. 环形子数组的最大和
【题目】:
给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和 。
环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i] 的下一个元素是 nums[(i + 1) % n] , nums[i] 的前一个元素是 nums[(i - 1 + n) % n] 。
&emsp子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], …, nums[j] ,不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n 。
【示例】:
输入:nums = [5,-3,5]
输出:10
解释:从子数组 [5,5] 得到最大和 5 + 5 = 10
提示:
n == nums.length
1 <= n <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
【分析】:
显然如果我们"死板"按照题目所说的环形数组进行分析,会感到无从下手。所以我们可以换一种思路:我们对数组被偷元素是否包含首尾,进行分类讨论。从而将环形数组问题转化称求普通子数组的最大和问题!
分类情况:
-
首位元素都被选,此时我们将原问题转化成求普通数组中子数组的最小和。最后用整个数组的和减去最小和,间接求出该情况最大值。
-
首位元素不全都被选。此时原问题转化成普通数组中子数组的最大和。
如何求普通数组最大子数组和、最小子数组和:
这里我们可以定义fi]表示以i位置为结尾的子数组最大和,g[i]表示以i位置为结尾的子数组最小和。
状态转移方程推导:
- 以i位置为结尾的子数组最大和分两种情况:如果f[i-1] >0, 此时最大子数组和为f[i-1] + nums[i]。否则最大子数组和为nums[i]本身。所以状态转移方程为:
f[i] = max(nums[i], dp[i-1] + nums[i])
。 - 同理,以i位置为结尾的子数组最小和分两种情况:如果f[i-1] <0, 此时最小子数组和为f[i-1] + nums[i]。否则最小子数组和为nums[i]本身。所以状态转移方程为:
g[i] = min(g[i-1]+ nums[i], nums[i])
细节处理:
显然不管是求f[i]还是g[i],当i为0时,状态转移方程失效。这里各位办法是给f、g都额外新增一个空间。最后从左往右依次填表即可。
如果数组中元素全为负数时,此时子数组和最大值一定为负数。但此时我们发现g[i]最终求得的子数组最小和就是整个数组和,此时数组和减子数组最小和的最终结果为0。需要单独处理
【代码编写】:
class Solution {
public:int maxSubarraySumCircular(vector<int>& nums) {//数组和int sum = 0;for(auto x : nums){sum += x;}int n = nums.size();vector<int> f(n + 1);//普通数组最大连续子数组和auto g = f;//普通数组最小连续子数组和int fmax = INT_MIN, gmin = INT_MAX;//分别统计f中最大值,g中最小值for(int i = 1; i <= n; i++){f[i] = max(nums[i - 1], f[i - 1] + nums[i - 1]);fmax = max(fmax, f[i]);g[i] = min(nums[i - 1], g[i - 1] + nums[i - 1]);gmin = min(gmin, g[i]);}return sum == gmin ? fmax : max(fmax, sum - gmin);//判断数组元素是否全为负数}
};
三、乘积最大子数组
【题目链接】:152. 乘积最大子数组
【题目】:
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
&emsp测试用例的答案是一个 32-位 整数。
【示例】:
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
【分析】:
我们可以定义f[i]表示以i为结尾的最大子数组乘积,g[i]表示以i为结尾的最小子数组乘积。
状态转移方程推导
-
以i为结尾的子数组长度可能为1,或大于1。对于大于1的情况,如果nums[i]>0,此时最大子数组乘积为g[i-1]*nums[i];如果nums[i]<0,此时最大子数组乘积为g[i-1]*nums[i]。我们仅需直接求得3种情况的最大值即可,即状态转移方程为:
f[i] = max(nums[i - 1], max(f[i - 1] * nums[i - 1], g[i - 1] * nums[i - 1]))
。
-
同理对于g[i]来说,也存在如下几种情况。最终可得状态转移方程为
g[i] = min(nums[i - 1], min(g[i - 1] * nums[i - 1], f[i - 1] * nums[i - 1]));
细节处理:
当i=0时,f、g的状态转移方程不适用。我们可以为f、g额外增加1个空间。同时为了防止新增结果对后续填表造成影响,我们将g[0]、f[0]初始化为1。
【代码编写】
public:int maxProduct(vector<int>& nums) {int n = nums.size();vector<int> f(n + 1);//f[i]表示以i为结尾的子数组的最大乘积auto g = f;//g[i]表示以i为结尾的子数组的最小乘积int ret = INT_MIN;f[0] = 1, g[0] = 1;for(int i = 1; i <= n; i++){f[i] = max(nums[i - 1], max(f[i - 1] * nums[i - 1], g[i - 1] * nums[i - 1]));g[i] = min(nums[i - 1], min(g[i - 1] * nums[i - 1], f[i - 1] * nums[i - 1]));ret = max(ret, f[i]);}return ret;}
};
四、乘积为正数的最长子数组长度
【题目链接】:1567. 乘积为正数的最长子数组长度
【题目】:
给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。
请你返回乘积为正数的最长子数组长度。
【示例】:
输入:nums = [-1,-2,-3,0,1]
输出:2
解释:乘积为正数的最长子数组是 [-1,-2] 或者 [-2,-3] 。
【分析】:
我们定义f[i]表示以i为结尾,乘积为正的子数组最长长度;g[i]表示以i为结尾,乘积为负的子数组最长长度。
状态转移方程推导:
我们可以从最后一个元素nums[i[入手,此时分为以下几种情况:
- 最长子数组长度可能为1,或大于1,具体如下:
将上述情况仅需合并后,可得:
- 同理,g[i]的情况如下:
合并后,可得:
细节处理:
显然当i为0时,f、g的状态转移方程都失效。所以我们给f、g额外增加一个空间。为了保证新增空间对后续填表结果不造成印象,我们将f[0]、g[0]初始化为0。最后从左往右填表即可。
【代码编写】:
class Solution {
public:int getMaxLen(vector<int>& nums) {int n = nums.size();vector<int> f(n + 1);//f[i]: 以i为结尾的,乘积为正的最长子数组长度auto g = f;//g[i]: 以i为结尾的,乘积为负的最长子数组长度int ret = INT_MIN;for(int i = 1; i <= n; i++){if(nums[i - 1] > 0){f[i] = f[i - 1] + 1;g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;}else if(nums[i - 1] < 0){f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;g[i] = f[i - 1] + 1;}ret = max(ret, f[i]);}return ret;}
};
相关文章:
算法沉淀——动态规划篇(子数组系列问题(上))
算法沉淀——动态规划篇(子数组系列问题(上)) 前言一、最大子数组和二、环形子数组的最大和三、乘积最大子数组四、乘积为正数的最长子数组长度 前言 几乎所有的动态规划问题大致可分为以下5个步骤,后续所有问题分析都…...
通知中心架构:打造高效沟通平台,提升信息传递效率
随着信息技术的快速发展,通知中心架构作为一种关键的沟通工具,正逐渐成为各类应用和系统中必不可少的组成部分。本文将深入探讨通知中心架构的意义、设计原则以及在实际场景中的应用。 ### 什么是通知中心架构? 通知中心架构是指通过集中管…...
【Arduino使用SNR9816TTS模块教程】
【Arduino使用SNR9816TTS模块教程】 1.前言2. 硬件连接3. Arduino代码3.1 环境配置3.2 Arduino源码 4. 调试步骤5. 总结 1.前言 在今天的教程中,我们将详细介绍如何使用Arduino IDE开发ESP32C3与汕头新纳捷科技有限公司生产的SNR9816TTS中文人声语音合成模块进行交…...
牛客练习赛123(A,B,C,D)
牛客挑战赛,练习赛和小白月赛周赛不是一种东西。这玩意跟CF的div12差不多难度。而且找不到题解。所以决定不等题解补题了,直接写题解了。 比赛链接 光速签到下班,rk。感觉E可能能补掉,看情况补吧。 B题感觉之前考了两次&#x…...
docker部署-RabbitMq
1. 参考 RabbitMq官网 docker官网 2. 拉取镜像 这里改为自己需要的版本即可,下面容器也需要同理修改 docker pull rabbitmq:3.12-management3. 运行容器 docker run \ --namemy-rabbitmq-01 \ -p 5672:5672 \ -p 15672:15672 \ -d \ --restart always \ -…...
【智能算法】蜜獾算法(HBA)原理及实现
目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2021年,FA Hashim等人受到自然界中蜜獾狩猎行为启发,提出了蜜獾算法((Honey Badger Algorithm,HBA)。 2.算法原理 2.1算法思想 蜜獾以其…...
9、鸿蒙学习-开发及引用静态共享包(API 9)
HAR(Harmony Archive)是静态共享包,可以包含代码、C库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。…...
[Pytorch]:PyTorch中张量乘法大全
在 PyTorch 中,有多种方法可以执行张量之间的乘法。这里列出了一些常见的乘法操作: 总结: 逐元素乘法:*ortorch.mul()矩阵乘法:ortorch.mm()ortorch.matmul()点积:torch.Tensor.dot()批量矩阵乘法ÿ…...
【软考】防火墙技术
目录 1. 概念2. 包过滤防火墙3. 应用代理网关防火墙4. 状态检测技术防火墙 1. 概念 1.防火墙(Firewall)是建立在内外网络边界上的过滤封锁机制,它认为内部网络是安全和可信赖的,而外部网络是不安全和不可信赖的。2.防火墙的作用是防止不希望的、未经授权…...
OpenHarmony实战:Makefile方式组织编译的库移植
以yxml库为例,其移植过程如下文所示。 源码获取 从仓库获取yxml源码,其目录结构如下表: 表1 源码目录结构 名称描述yxml/bench/benchmark相关代码yxml/test/测试输入输出文件,及测试脚本yxml/Makefile编译组织文件yxml/.gitat…...
嵌入式C语言--GPT通用定时器
嵌入式C语言–GPT通用定时器 嵌入式C语言--GPT通用定时器 嵌入式C语言--GPT通用定时器一. GPT基本概念二. GPT的作用三. GPT通道的四个状态四. Continuous/One-Shot模式3.1)Continuous模式3.2)One-Shot模式 一. GPT基本概念 GPT即General Purpose Timer…...
『Apisix系列』破局传统架构:探索新一代微服务体系下的API管理新范式与最佳实践
一、『Apisix安装部署』 🚀 1.1 手把手教你从零部署APISIX高性能API网关 二、『Apisix入门篇』 🚀 2.1 从零到一掌握Apache APISIX:架构解析与实战指南 三、『Apisix进阶篇』 🚀 3.1 动态负载均衡:APISIX的实战演练…...
如何在极狐GitLab 自定义 Pages 域名、SSL/TLS 证书
本文作者:徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了在极狐GitLab 用户…...
React Native 应用打包
引言 在将React Native应用上架至App Store时,除了通常的上架流程外,还需考虑一些额外的优化策略。本文将介绍如何通过配置App Transport Security、Release Scheme和启动屏优化技巧来提升React Native应用的上架质量和用户体验。 配置 App Transport…...
单链表就地逆置
算法思想:构建一个带头结点的单链表L,然后访问链表中的每一个数据结点,将访问到的数据结点依此插入到L的头节点之后。 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef s…...
MTU/TCPMSS/VLAN/ACCESS/TRUNK/HYBRID
MTU RFC标准定义以太网的默认MTU值为1500 最小64字节是为了保证最极端的冲突能被检测到,64字节是能被检测到的最小值;最大不超过1518字节是为了防止过长的帧传输时间过长而占用共享链路太长时间导致其他业务阻塞。所以规定以太网帧大小为64~1518字节&am…...
Spring Boot的基础知识和应用
在快速发展的软件开发领域,Spring Boot已经成为了一个广受欢迎的框架,它极大地简化了Spring应用的初始搭建以及开发过程。Spring Boot遵循“约定优于配置”的原则,通过默认配置减少了开发者的配置工作量,使得开发者能够更专注于业…...
【Linux】详解动静态库的制作和使用动静态库在系统中的配置步骤
一、库的作用 1、提高开发效率,让开发者所有的函数实现不用从零开始。 2、隐藏源代码。 库其实就是所有的.o文件用特定的方式进行打包形成一个文件,各个.o文件包含了源代码中的机器语言指令。 二、动态库和静态库的制作和使用 2.1、静态库的制作和使用…...
开源模型应用落地-qwen1.5-7b-chat-LoRA微调(二)
一、前言 预训练模型提供的是通用能力,对于某些特定领域的问题可能不够擅长,通过微调可以让模型更适应这些特定领域的需求,让它更擅长解决具体的问题。 本篇是开源模型应用落地-qwen-7b-chat-LoRA微调(一)进阶篇,学习通义千问最新1.5系列模型的微调方式。 二、术语介绍 …...
【现代企业管理】企业组织结构和组织文化的理论与实践——以华为为例
一、前言 管理是科学和艺术的统一体,它是企业成长的保证。企业管理中,管理者面对的往往不是一个完整的系统,而是各种不具有整体规律性的零碎信息的总和,因此进行信息的整合和研究是管理的重点和关键。 组织管理作为管理的四大职…...
【Kotlin】Sequence简介
1 前言 序列(Sequence)是 Kotlin 中为方便操作集合及其元素而定制的接口,是一个延迟获取数据的集合,只有需要元素时才会生产元素。在处理大量数据时,序列可以显著地提升性能。 Sequence 类似 Java 中的 Stream…...
【Java】Thread详解
🍒前言 本文将从以下几方面来展开对Thread的介绍。 1.线程创建 2.线程中断 3.线程等待 4.线程休眠 在前面的文章中,已经总结了关于Thread的一些理解。 在阅读本文之前,最好对其有一些基础的了解。 文章链接: 【JavaSE】进程是什么?…...
QT TCP和UDP网络编程
代表网络概念的QTcpSocket,QTcpServer和QUdpSocket,以及QNetworkRequest,QNetworkReply和QNetworkAccessManager之类的高级类来执行使用通用协议的网络操作。 它还提供了QNetworkConfiguration,QNetworkConfigurationManager和QNetworkSession等,实现承载…...
Maven入门指南:构建与管理Java项目的利器
引言 在Java开发领域,项目构建和管理是一个至关重要的环节。随着项目规模和复杂度的不断增加,有效地管理项目的依赖、构建过程以及部署流程变得尤为关键。在这样的背景下,Apache Maven作为一款优秀的项目管理工具应运而生,成为了…...
EXCEL-VB编程实现自动抓取多工作簿多工作表中的单元格数据
一、VB编程基础 1、 EXCEL文件启动宏设置 文件-选项-信任中心-信任中心设置-宏设置-启用所有宏 汇总文件保存必须以宏启动工作簿格式类型进行保存 2、 VB编程界面与入门 参考收藏 https://blog.csdn.net/O_MMMM_O/article/details/107260402?spm1001.2014.3001.5506 二、…...
用Vue仿了一个类似抖音的App
大家好,我是 Java陈序员。 今天,给大家介绍一个基于 Vue3 实现的高仿抖音开源项目。 关注微信公众号:【Java陈序员】,获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。 项目介绍 douyin —— 一个基于 Vue、Vite 实…...
HarmonyOS 应用开发之非线性容器
非线性容器实现能快速查找的数据结构,其底层通过hash或者红黑树实现,包括HashMap、HashSet、TreeMap、TreeSet、LightWeightMap、LightWeightSet、PlainArray七种。非线性容器中的key及value的类型均满足ECMA标准。 HashMap HashMap 可用来存储具有关联…...
Golang Context是什么
一、这篇文章我们简要讨论Golang的Context有什么用 1、首先说一下Context的基本作用,然后在讨论他的实现 (1)数据传递,子Context只能看到自己的和父Context的数据,子Context是不能看到孙Context添加的数据。 (2)父子协程的协同,比…...
算法基础--递推
😀前言 递推算法在计算机科学中扮演着重要的角色。通过递推,我们可以根据已知的初始条件,通过一定的规则推导出后续的结果,从而解决各种实际问题。本文将介绍递推算法的基础知识,并通过一些入门例题来帮助读者更好地理…...
超市销售数据-python数据分析项目
Python数据分析项目-基于Python的销售数据分析项目 文章目录 Python数据分析项目-基于Python的销售数据分析项目项目介绍数据分析结果导出数据查阅 数据分析内容哪些类别比较畅销?哪些商品比较畅销?不同门店的销售额占比哪个时间段是超市的客流高封期?查看源数据类型计算本月…...
上海公司注册核名查询/黑帽seo教程
为什么80%的码农都做不了架构师?>>> 首先说一下Redis公认的特点: Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。Redis不仅仅支持简单的key-value类型的数据,同…...
wordpress多语言生成工具/百度收录提交网址
原文 http://www.cnblogs.com/meteoric_cry/p/4285881.html主题 curllibcurl参数很多,一不小心就容易遇到问题。曾经就遇到过一个很蛋疼的问题:libcurl断点下载>> 这里主要汇总一下,libcurl上传的二种方式: 1、直接上传文件…...
建设网站销售/推广网站公司
我用来绕过“完整路径和文件名”长度限制以移动,复制或删除某些内容的一个技巧是,通过使用指向文件夹的映射驱动器号 “中途”(或更多)“ 插入 ”来缩短它顺路。所以你有c:\ some \ long \ path ... \ and \ foo \ bar \ folders \ oldfiles …...
wordpress 游客留言/怎么自己开网站
前提条件: (1) zabbix服务器端已经成功安装并且运行。 (2) zabbix客户端已经成功建立并且运行。 1 下载并且安装msmtp软件 Wget http://sourceforge.net/projects/msmtp/files/msmtp/1.4.32/msmtp-1.4.32.tar.bz2/download tar jxvf msmtp-1.4.32.tar.bz2 cd ms…...
南宁建设网站制作/关键词挖掘
设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 输出格式: 输出分2行&a…...
青海省建设厅网站人才集合/logo设计
操作与控制 安全要求 系统组件安装 系统调试 分析题 转载于:https://www.cnblogs.com/shan1393/p/10246815.html...