算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)

💕"我们好像在池塘的水底,从一个月亮走向另一个月亮。"💕
作者:Mylvzi
文章主要内容:算法系列–动态规划–⼦数组、⼦串系列(数组中连续的⼀段)(1)
在这里插入图片描述

大家好,今天为大家带来的是算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1),这是动态规划新的一种题型

1.最⼤⼦数组和

链接:
https://leetcode.cn/problems/maximum-subarray/
分析:

动态规划的子数组问题和前缀和问题是不一样的,

子数组和这道题要求的是子数组和的最大值,我们的状态表示就是记录以i位置为结束的所有子数组的最大和,而前缀和只是一种快速求出区间和的方法,并没有表示最大和这种状态

关于求最大子数组和问题这道题,要注意状态表示的含义以i位置为结尾的所有子数组的最大和,也就是必须以i位置为结尾,那么此时的状态其实只有两种:

  1. 单独一个
  2. 前面的一堆 + 它本身

网上的很多推到状态方程的时候其实很容易让人误解,解释的也不清楚,他们进行状态的分类是根据dp[i - 1]的正负来推导dp[i]的,有的人可能想为什么不判断nums[i]的正负呢?

其实本质都一样,笔者觉得单纯通过形式来推到方程更容易理解一些

子串/子数组问题的一个经验的状态分类就是按照长度分类的,因为他们的状态表示都比较固定,都是以i位置为结束的最大xxxx

有的题目还比较恶心(尤其是关于子串的问题),对于相同的子串有时候还需要去重,就需要额外开一个数组来统计次数

本题的分析思路:
在这里插入图片描述

代码:

class Solution {public int maxSubArray(int[] nums) {int n = nums.length;int dp = 0;int max = -0x3f3f3f3f;// 将最大/小值设置为+-ox3f3f3f3f是一种经验for(int num : nums) {dp = Math.max(num,dp + num);// 填表max = Math.max(max,dp);// 更新最值}return max;}
}

2.环形⼦数组的最⼤和

链接:
https://leetcode.cn/problems/maximum-sum-circular-subarray/description/
分析:

本题是上题的一个变种,这里带环了,对于带环的问题,我们最常用的一个做法是想办法将其转化为线性的,对于本题我们可以采用分类讨论的思想

根据什么区分类讨论呢?往往是根据最后结果可能出现的形式去考虑,对于本题,最长的子数组和可能是两种情况

  1. 不带环,在区间内部
  2. 带环,跨越区间

对于情况1,就是最大子数组和的解法,对于情况2,可以转化为求区间内的最小值,那么最大值就是sum - min,最后返回情况1和情况2的最大值即可

下面是详细分析过程

在这里插入图片描述

代码:

class Solution {public int maxSubarraySumCircular(int[] nums) {// 创建dp表int n = nums.length;if(n == 1) return nums[0];int[] f = new int[n];int[] g = new int[n];// 初始化f[0] = g[0] = nums[0];int max = -0x3f3f3f3f;int min = 0x3f3f3f3f;int sum = nums[0];// 填表for(int i = 1; i < n; i++) {f[i] = Math.max(nums[i],f[i - 1] + nums[i]);g[i] = Math.min(nums[i],g[i - 1] + nums[i]);max = Math.max(max,f[i]);min = Math.min(min,g[i]);sum += nums[i];}// 返回值return sum == min ? max : Math.max(max,sum - min);}
}

3.乘积最⼤⼦数组

链接:
https://leetcode.cn/problems/maximum-product-subarray/
分析:

首先想到的状态表示就是以i位置为结尾子数组的最大乘积,但是根据这个状态表示去推到状态转移方程时发现只使用一个dp表无法表示所有的情况

  • nums[i] > 0,i位置的状态就是前一个位置的最大乘积 * nums[i]
  • nums[i] < 0,此时无法通过dp[i - 1]来推到dp[i],因为一个负数 * 较大的数一定会变小,那么dp[i]存储的就是以i位置为结尾的子数组的最小乘积,这与我们的状态表示是矛盾的

既然当nums[i] < 0时,需要乘的是以i-1位置为结尾的子数组的最小乘积,那么我们就创建出一个dp表g[i]来表示最小乘积,以下是详细分析过程:
在这里插入图片描述

代码:

class Solution {public int maxProduct(int[] nums) {// 创建dp表int n = nums.length;int[] f = new int[n];int[] g = new int[n];// 初始化f[0] = g[0] = nums[0];int max = f[0];// 填表for(int i = 1; i < n; i++) {int t1 = 0, t2 = 0;if(nums[i] > 0) {f[i] = f[i - 1] * nums[i];g[i] = g[i - 1] * nums[i];}else {f[i] = g[i - 1] * nums[i];g[i] = f[i - 1] * nums[i];}f[i] = Math.max(nums[i],f[i]);g[i] = Math.min(nums[i],g[i]);max = Math.max(f[i],max);}return max;}
}

4.乘积为正数的最⻓⼦数组

链接:
https://leetcode.cn/problems/maximum-length-of-subarray-with-positive-product/description/
分析:

本题相较于上题有两个不同:

  1. 本题要求乘积必须为正数
  2. 本题求解的不是最大的乘积,而是乘积为正数的最长子数组

和上题一样,本题同样需要使用两个dp表来进行状态表示

  • f[i]:以i位置为结尾,乘积为正数的最大子数组长度
  • g[i]:以i位置为结尾,乘积为负数的最大子数组长度

状态转移方程推导如下:

在这里插入图片描述

注意特殊情况:

  • 当n[i] < 0时,f[i] == g[i - 1] + 1,但是如果i位置之前全是正数,此时g[i - 1] == 0,那么f[i] == 0 + 1 = 1了,但是因为n[i] < 0,i位置的f[i]应该等于 0,因为所有的以i位置为结尾的子数组的乘积必然为负数

代码:

class Solution {public int getMaxLen(int[] nums) {int n = nums.length;// 1.创建dp表int[] f = new int[n];int[] g = new int[n];// 2.根据状态表示进行初始化f[0] = nums[0] > 0 ? 1 : 0;g[0] = nums[0] < 0 ? 1 : 0;int max = -0x3f3f3f3f;// 3.填表for(int i = 1; i < n; i++) {if(nums[i] > 0) {f[i] = f[i - 1] + 1;g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;}else if(nums[i] < 0){f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;g[i] = f[i - 1] + 1;}else {f[i] = g[i] = 0;// 注意等于0相当于直接截断 要重新计数 从0开始}max = Math.max(f[i],max);// 更新长度}// 处理n == 1的情况return max == -0x3f3f3f3f ? f[0] : max;}
}

总结:

  • 子数组问题最常用的一种状态表示就是以i位置为结尾的xxxx
  • 在推导状态转移方程时,往往是根据组成子数组的形态来分类讨论(单独一个还是和前面一堆组成子数组)

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

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

相关文章

PPP实验

PPP实验 一.实验思路 1.对接口进行配置IP 2.将R2上面的两个serial接口与R3的两个接口进行链路聚合&#xff0c;然后配置IP 3.在R2&#xff08;验证方&#xff09;上配置PPP chap协议 4.在R1上配置验证用户名 5.要使R3和R2能进行双向chap验证&#xff0c;要在R3上配置ppp chap协…

软件设计师19--文件管理

软件设计师19--文件管理 考点1&#xff1a;文件相关概念例题&#xff1a; 考点2&#xff1a;树形目录结构&#xff08;绝对路径与相对路径&#xff09;例题&#xff1a; 考点3&#xff1a;位示图例题&#xff1a; 考点4&#xff1a;索引文件索引文件结构例题&#xff1a; 考点1…

背包DP模板

01背包 01背包-1 #include <bits/stdc.h> using namespace std;const int N 1e5 10; int n, m, f[N][N], v[N], w[N];int main() {cin >> n >> m;for (int i 1; i < n; i) {cin >> v[i] >> w[i];}for (int i 1; i < n; i) {for (int…

安装element ui失败,解决版本冲突问题

解决方法 降低npm的版本 npm install -g npm6.14.8 不用回退 命令&#xff1a;npm install --legacy-peer-deps element-ui --save

【C++】手撕哈希表的闭散列和开散列

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;手撕哈希表的闭散列和开散列 > 毒鸡汤&#xff1a;谁不是一边受伤&#xff0c;一边学会坚强。 > 专栏选自&#xff1a;C嘎嘎进阶 > 望小伙伴们…

后端代码1

// 新增 public JsonResultVo<?> create(ApiIgnore RequestAttribute(ConstVal.REQ_USER) BaseUser baseUser,RequestBody IUTradeBuyPreserveVo iuTradeBuyPreserveVo) {//权限判断if (!baseCompanyService.dataPermission(baseUser, iuTradeBuyPreserveVo.getCompanyi…

wma怎么转换成mp3?无损转换!

WMA&#xff08;Windows Media Audio&#xff09;文件格式诞生于微软公司的数字音频技术研发。由于其高压缩性能和较好的音质&#xff0c;在推出初期主要用于Windows Media Player等微软产品。然而&#xff0c;随着MP3格式的盛行&#xff0c;WMA的使用范围逐渐受到限制。 MP3文…

pytorch简单的优化问题实战

目录 1. Himmelblau函数2. python画出函数图3. 梯度优化代码 1. Himmelblau函数 如下图&#xff1a; 从图中的碗一样的图中可以看出有4个极值点&#xff0c;那么经过优化后&#xff0c;会有4个结果。 4个点的结果见下图&#xff1a; 2. python画出函数图 3. 梯度优化代码 源…

西圣VS飞利浦VS倍思开放式耳机哪款值得入手?爆款产品无广大测评

在当今这个无线耳机盛行的时代&#xff0c;开放式耳机以其独特的佩戴舒适度和出色的音质体验&#xff0c;逐渐赢得了消费者的青睐&#xff0c;西圣、飞利浦、倍思作为市场上的知名品牌&#xff0c;都推出了各具特色的开放式耳机产品&#xff0c;许多消费者也因此不知道哪款更加…

在vue中使用echarts饼图示例

1.安装 npm install echarts --save 2.官方示例 option {title: {text: Referer of a Website,subtext: Fake Data,left: center},tooltip: {trigger: item},legend: {orient: vertical,left: left},series: [{name: Access From,type: pie,radius: 50%,data: [{ value: 104…

用css滤镜做颜色不同的数据卡片(背景图对于css滤镜的使用)

<template> <div class"xx_modal_maincon"><div class"xx_model_bt">履约起始日至计算日配额及履约情况</div><el-row><el-col :span"6"><div class"xx_modal_mod"><div class"mod…

虚拟机Linux-openEuler硬盘空间扩容

虚拟机Linux-openEuler硬盘空间扩容 1、需求场景 我们在使用虚拟机时&#xff0c;可能会出现磁盘空间不够用导致各种bug出现的情况。 首先&#xff0c;我们要扩展虚拟机的可用磁盘空间。如图所示&#xff0c;我的原本硬盘大小为8G&#xff0c;我们扩展到30GB 2、打开虚拟机…

android_uiautomator元素定位

通过UIAUTOMATOR的text属性定位到元素&#xff0c;并打印文本from appium import webdriver from appium.webdriver.common.appiumby import AppiumBy import time # For W3C actions from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriv…

1_88. 合并两个有序数组

1_88. 合并两个有序数组 难度: 简单 提示: 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。请你合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意…

使用U盘重装CentOS7系统

下载CentOS7 系统镜像 制作启动U盘之前&#xff0c;首先要准备一个系统镜像&#xff0c;这里我在CentOS官网直接下载镜像文件&#xff1a; CentOS官网 为了保证下载速度&#xff0c;这里我使用阿里云镜像下载&#xff1a; 阿里云镜像 如上图所示&#xff0c;我需要一个带UI界…

ES 进阶知识

索引Index 一个索引就是一个拥有几分相似特征的文档的集合。比如说&#xff0c;你可以有一个客户数据的索引&#xff0c;另一个产品目录的索引&#xff0c;还有一个订单数据的索引。一个索引由一个名字来标识&#xff08;必须全部是小写字母&#xff09;&#xff0c;并且当我们…

pytorch代码中optimizer.step()和scheduler.step()有什么区别

optimizer.step()通常用在每个patch_size之中(一个patch_size的数据更新一次模型参数)&#xff0c;而scheduler.step()通常用在epoch里面,但是不绝对&#xff0c;可以根据具体的需求来做。只有用了optimizer.step()&#xff0c;模型才会更新&#xff0c;而scheduler.step()是对…

【机器学习】无监督学习算法之:K均值聚类

K均值聚类 1、引言2、K均值聚类2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.4.1 距离计算公式2.4.1 中心点计算公式 2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; K均值聚类 我不懂&#xff0c;能不能给我讲一讲&#xff1f; 小鱼&#xff1a;行&#xf…

latex在写算法`\For` 和 `\EndFor` 以及 `FOR` 和 `\ENDFOR` ,报错Undefined control sequence.

这里写目录标题 1. 错误原因2. 进行改正3. 爱思唯尔期刊与施普林格期刊对于算法的格式不太一样&#xff0c;不能直接套用总结 1. 错误原因 我在算法中使用\For&#xff0c;\EndFor 2. 进行改正 换成FOR&#xff0c;\ENDFOR 3. 爱思唯尔期刊与施普林格期刊对于算法的格式不太…