当前位置: 首页 > news >正文

算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(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
  • 在推导状态转移方程时,往往是根据组成子数组的形态来分类讨论(单独一个还是和前面一堆组成子数组)

相关文章:

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

&#x1f495;"我们好像在池塘的水底&#xff0c;从一个月亮走向另一个月亮。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;算法系列–动态规划–⼦数组、⼦串系列&#xff08;数组中连续的⼀段&#xff09;(1) 大家好,今天为大家带来的是算法系…...

RESTful架构

RESTful架构中的URI设计与传统的URL设计有一些区别。让我通过具体的例子来解释一下&#xff1a; 传统的URL设计通常将操作和资源混合在一起&#xff0c;例如&#xff1a; 获取所有图书&#xff1a;GET /getBooks获取特定图书&#xff1a;GET /getBookById/{id}创建新图书&…...

从IO操作与多线程的思考到Redis-6.0

IO操作->线程阻塞->释放CPU资源->多线程技术提升CPU利用率 在没有涉及磁盘操作和网络请求的程序中&#xff0c;通常不会出现线程等待状态。线程等待状态通常是由于线程需要等待某些事件的发生&#xff0c;比如I/O操作完成、网络请求返回等。如果程序只是进行计算或者简…...

MNN介绍、安装和编译

MNN是一个轻量级的深度学习推理框架&#xff0c;由阿里巴巴公司开发。它支持多种硬件平台&#xff0c;包括CPU、GPU和NPU&#xff0c;并提供高效、高性能的深度学习模型推理服务。下面是MNN的安装和编译步骤&#xff1a; 下载MNN源代码 在MNN的GitHub页面&#xff08;https://g…...

【计算机图形学】AO-Grasp: Articulated Object Grasp Generation

对AO-Grasp: Articulated Object Grasp Generation的简单理解 文章目录 1. 做的事情2. AO-Grasp数据集2.1 抓取参数化和label标准2.2 语义和几何感知的抓取采样 3. AO-Grasp抓取预测3.1 预测抓取点3.2 抓取方向预测 4. 总结 1. 做的事情 引入AO-Grasp&#xff0c;grasp propo…...

「媒体宣传」财经类媒体邀约资源有哪些?-51媒体

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 财经类媒体邀约资源包括但不限于以下几类&#xff1a; 商业杂志和报纸&#xff1a;可以邀请如《财经》、《新财富》、《经济观察报》等主流商业杂志和报纸。这些媒体通常具有较强的品牌影…...

学习资料记录

http://interview.wzcu.com/Golang/%E4%BB%A3%E7%A0%81%E8%80%83%E9%A2%98.html map底层 https://zhuanlan.zhihu.com/p/616979764 go修养 https://www.yuque.com/aceld/golang/ga6pb1#4b19dba5 https://golang.dbwu.tech/performance/map_pre_alloc/ https://juejin.cn/pos…...

数据结构进阶篇 之 【二叉树】详细概念讲解(带你认识何为二叉树及其性质)

有朋自远方来&#xff0c;必先苦其心志&#xff0c;劳其筋骨&#xff0c;饿其体肤&#xff0c;空乏其身&#xff0c;鞭数十&#xff0c;驱之别院 一、二叉树 1、二叉树的概念 1.1 二叉树中组分构成名词概念 1.2 二叉树的结构概念 1.3 特殊的二叉树 2、二叉树的存储结构 …...

vue.js制作学习计划表案例

通俗易懂&#xff0c;完成“学习计划表”用于对学习计划进行管理&#xff0c;包括对学习计划进行添加、删除、修改等操作。 一. 初始页面效果展示 二.添加学习计划页面效果展示 三.修改学习计划完成状态的页面效果展示 四.删除学习计划 当学习计划处于“已完成”状态时&…...

nginx localtion 匹配规则

1、语法规则 语法规则&#xff1a;location[|~|^~*|^~]/uri/{… } 表示精确匹配,这个优先级也是最高的 ^~ 表示 uri 以某个常规字符串开头&#xff0c;理解为匹配 url 路径即可。 nginx 不对 url 做编码&#xff0c;因此请求为 /image/20%/aa&#xff0c;可以被规则^~ /imag…...

Git:分布式版本控制系统

目录 Git的特点和功能常见的功能和对应的命令 Git的特点和功能 Git是一个分布式版本控制系统&#xff0c;用于跟踪和管理项目的代码变更。它是由Linus Torvalds在2005年创建的&#xff0c;旨在管理Linux内核的开发。Git具有以下特点和功能&#xff1a; 分布式版本控制&#xf…...

[STL]priority_queue类及反向迭代器的模拟实现

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a; priority_queue类及反向迭代器 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 向着c&…...

vue2 脚手架

安装 文档&#xff1a;https://cli.vuejs.org/zh/ 第一步&#xff1a;全局安装&#xff08;仅第一次执行&#xff09; npm install -g vue/cli 或 yarn global add vue/cli 备注&#xff1a;如果出现下载缓慢&#xff1a;请配置npm 淘宝镜像&#xff1a; npm config set regis…...

【OpenStack】OpenStack实战之开篇

目录 那么,OpenStack是什么?云又是什么?关于容器应用程序OpenStack如何适配其中?如何设置它?如何学会使用它?推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战我的整个职业生涯到目前为止一直围绕着为离线或隔离网络设计和开发应用程…...

Python实现WebSocket通信

WebSocket是一种在单个TCP连接上进行全双工通信的协议,位于 OSI 模型的应用层。 与传统的HTTP请求-响应模型不同&#xff0c;WebSocket的最大特点就是&#xff0c;服务器可以主动向客户端推送信息&#xff0c;客户端也可以主动向服务器发送信息&#xff0c;实现实时性和互动性…...

MATLAB 自定义生成直线点云(详细介绍) (47)

MATLAB 自定义生成直线点云 (详细介绍)(47) 一、算法介绍二、具体步骤二、算法实现1.代码2.效果一、算法介绍 通过这里的直线生成方法,可以生成模拟直线的点云数据,并通过调整起点、终点、数量和噪声水平等参数来探索不同类型的直线数据。这种方法可以用于测试、验证和开…...

UniTask 异步任务

文章目录 前言一、UniTask是什么&#xff1f;二、使用步骤三、常用的UniTask API和示例1.编写异步方法2.处理异常3.延迟执行4.等待多个UniTask或者一个UniTas完成5.异步加载资源示例6.手动控制UniTask的完成状态7.UniTask.Lazy延迟任务的创建8.后台线程切换Unity主线程9.不要返…...

【git分支管理策略】如何高效的管理好代码版本

目录 1.分支管理策略 2.我用的分支管理策略 3.一些常见问题 1.分支管理策略 分支管理策略就是一些经过实践后总结出来的可靠的分支管理的办法&#xff0c;让分支之间能科学合理、高效的进行协作&#xff0c;帮助我们在整个开发流程中合理的管理好代码版本。 目前有两套Git…...

css的transition详解

CSS的transition属性是一个简写属性&#xff0c;用于设置四个过渡效果属性&#xff0c;以在元素的状态改变时创建平滑的动画效果。这四个属性分别是&#xff1a; transition-property&#xff1a; 定义应用过渡效果的CSS属性名称。当指定的CSS属性改变时&#xff0c;过渡效果将…...

agent利用知识来做规划:《KnowAgent: Knowledge-Augmented Planning for LLM-Based Agents》笔记

文章目录 简介KnowAgent思路准备知识Action Knowledge的定义Planning Path Generation with Action KnowledgePlanning Path Refinement via Knowledgeable Self-LearningKnowAgent的实验结果 总结参考资料 简介 《KnowAgent: Knowledge-Augmented Planning for LLM-Based Age…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...

AWS vs 阿里云:功能、服务与性能对比指南

在云计算领域&#xff0c;Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商&#xff0c;各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5]&#xff0c;我将从功能、服务和性能三个方面进行结构化对比分析&#…...

简约商务通用宣传年终总结12套PPT模版分享

IOS风格企业宣传PPT模版&#xff0c;年终工作总结PPT模版&#xff0c;简约精致扁平化商务通用动画PPT模版&#xff0c;素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...