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

对于子数组问题的动态规划

前言

先讲讲我对于这个问题的理解吧

当谈到解决子数组问题时,动态规划(DP)是一个强大的工具,它在处理各种算法挑战时发挥着重要作用。动态规划是一种思想,它通过将问题分解成更小的子问题并以一种递归的方式解决它们,然后利用这些解决方案来构建原始问题的解。在动态规划中,我们经常会遇到两种状态:一种是单独成一段,另一种是以 i 结尾的子数组。

通过枚举和动态规划,我们可以有效地解决子数组问题。枚举法需要考虑所有可能的子数组组合,然后比较它们以找到最优解。这种方法通常需要较多的时间和空间,因为它需要枚举所有可能性。而动态规划则更加智能化,它通过保存历史记录来避免不必要的重复计算。这样,下次遍历时,我们可以利用之前的计算结果,从而大大提高了效率。

动态规划的一个常见技巧是前缀和,它可以帮助我们快速求出数组中任意子数组的和。前缀和的核心思想是将原始数组中每个位置的值累加起来,形成一个新的数组,然后利用这个新数组来快速计算子数组的和。这种方法在处理求子数组和的问题时非常实用,因为它将复杂度降低到了单一状态的动态规划。

另外,预处理也是动态规划中常用的技巧之一。通过将经常使用的数据存储起来,我们可以在需要时快速获取,从而减少计算时间。预处理的思想是在问题出现之前就对数据进行处理,以便在需要时能够迅速获取所需的信息。

综上所述,动态规划是一种强大的解决子数组问题的方法,通过合理利用枚举、动态规划、前缀和和预处理等技巧,我们可以高效地解决各种复杂的算法挑战,为问题提供简单明了的解决方案。

这是我记得笔记 

 

我准备了五道例题都是这些解决方案

1.求最大子数组的和

. - 力扣(LeetCode)

思路分析:这一题主要是使用动态规划,也可以使用前缀和,动态规划也是求子数组的普遍思路,有两种状态,1自己组成子数组 和 前面的组成子数组,所以状态转移方程也就是Max(nums[i],dp[i - 1] + nums[i])

 代码实现

  public int maxSubArray(int[] nums) {int n = nums.length;int[] dp = new int[n + 1];//以i位置为结尾的最大子数组和 (多状态 前面i - 1的子数组要  和 不要)// 初始化 (因为存在负数)dp[0] = -0x3f3f3f3f;//前面子数组都是以i - 1位置为结尾 或者 i位置自己构成一个数组for (int i = 1; i <= nums.length; i++) {dp[i] = Math.max(nums[i - 1], dp[i - 1] + nums[i - 1]);}int max = -0x3f3f3f3f;for (int i = 0; i < dp.length; i++) {max = Math.max(dp[i], max);}return max;}

2.求最大环形子数组

. - 力扣(LeetCode)

思路分析:

中间的是连续的所以求内部最小子数组和就好了, 或者中间成最大子数组和
//f[]表示以i位置为结尾的所有子数组中的最大值  //g[]表示以i位置为结尾的所有子数组中的最小值
//g[]就是为了处理边界。他通过计算中间部分的最小值来结算环的最大值

public int maxSubarraySumCircular(int[] nums) {int sum = 0;//用来处理最小值int n = nums.length;//1.状态表示int[] f = new int[n + 1],g = new int[n + 1];//2.状态转移方程    自己组成子数组  和  自己加上以 i-1位置结尾 的最大子数组//3.初始化 = 0 即可for (int i = 1; i <= n; i++) {f[i] = Math.max(f[i - 1] + nums[i - 1], nums[i - 1]);g[i] = Math.min(g[i - 1] + nums[i - 1], nums[i - 1]);sum += nums[i - 1];}int maxF = -0x3f3f3f3f;//统计结果int minG = 0x3f3f3f3f;//统计结果//可以和上面统一合并,一个循环就够了for (int i = 1; i <= n; i++) {maxF = Math.max(maxF,f[i]);minG = Math.min(minG,g[i]);}//为了防止全是负数返回0,所以sum - minG要和0做判断//因为  -8 - (-8) = 0;全是负数sum = -8 minG = -8 所以要返回maxFreturn Math.max(maxF,sum - minG == 0 ? maxF : sum - minG);}

3.和为k的子数组个数 

. - 力扣(LeetCode)

 思路分析:

//解法 动态规划  +  hash表   k == pre[i](i位置的前缀和) - pre[j - 1] //此时 [j,i]的子数组为k
 public int subarraySum(int[] nums, int k) {int count = 0;//统计出现了多少次int n = nums.length;HashMap < Integer, Integer > hash = new HashMap<>();//当词典使用,存储所有前缀和hash.put(0,1);//记录0出现了1次,防止前缀和单独构成答案//1.状态表示   以i位置为结尾的区间和int[] pre = new int[n + 1];//2.状态转移方程  pre[i] = pre[i - 1] + nums[i]//3.初始化  防止j - 1 越界 pre[0] = 0for (int i = 1; i <= n; i++) {pre[i] = pre[i - 1] + nums[i - 1];//下标映射,因为我的pre[0]是虚拟节点if (hash.containsKey(pre[i] - k)){count += hash.get(pre[i] - k);}hash.put(pre[i],hash.getOrDefault(pre[i],0) + 1);//键为前缀和的值 ,值为出现的次数}return count;}

 滚动数组优化形成前缀和

//因为上述我们只使用了,pre[i - 1] 和 pre[i] 这两种状态,所以可以使用滚动数组进行优化,设置两个变量即可//也就是我们熟知的前缀和public int subarraySum1(int[] nums, int k) {int count = 0;//统计出现了多少次int n = nums.length;HashMap < Integer, Integer > hash = new HashMap<>();//当词典使用,存储所有前缀和int pre = 0;hash.put(0,1);//记录0出现了1次,防止前缀和单独构成答案for (int i = 0; i < n; i++) {pre += nums[i];if (hash.containsKey(pre - k)){count += hash.get(pre - k);}hash.put(pre,hash.getOrDefault(pre,0) + 1);//键为前缀和的值 ,值为出现的次数}return count;}

4.乘积为k的最大子数组

 

. - 力扣(LeetCode)

思路分析:注释都有明确标注状态表示和转移方程

 public int maxProduct(int[] nums) {int n = nums.length;//1.定义状态表示int[] f = new int[n + 1];//以i位置为结尾  所有子数组中 乘积的最大值   遇到正数我要你int[] g = new int[n + 1];//以i位置为结尾  所有子数组中 乘积的最小值   遇到负数我要你//2.状态转移方程  遇到正数我要最大值(f[i - 1])    遇到负数我要最小值(g[i - 1])//3.初始化  防止i - 1越界但不可保存0,因为初始化的初衷就是保证后续的位置不受影响f[0] = g[0] = 1;//注意多次赋值是从右往左进行的int ret = -0x3f3f3f3f;for (int i = 1; i <= n; i++) {if (nums[i - 1] > 0){f[i] = Math.max(f[i - 1] * nums[i - 1],nums[i - 1]);g[i] = Math.min(g[i - 1] * nums[i - 1],nums[i - 1]);}else {f[i] = Math.max(g[i - 1] * nums[i - 1],nums[i - 1]);g[i] = Math.min(f[i - 1] * nums[i - 1],nums[i - 1]);}ret = Math.max(ret,f[i]);}return ret;}

5.乘积为正数的最长子数组长度

. - 力扣(LeetCode)

 public int getMaxLen(int[] nums) {int n = nums.length;int ret = 0;//统计//1.状态表示int[] f = new int[n + 1];//以i位置为结尾中的 所有子数组中的 乘积为正数的最大长度int[] g = new int[n + 1];//以i位置为结尾中的 所有子数组中的 乘积为负数的最大长度//2.状态转移方程  f[i]如果i位置为正数为 f[i - 1] + 1    负数 g[i - 1] + 1//              g[i]同理正数g[i - 1] + 1   负数 f[i - 1] + 1//3.初始化 默认长度为0不影响后续结果for (int i = 1; i <= n; i++) {if (nums[i - 1] > 0){f[i] = f[i - 1] + 1;//当最后一个元素为正数的时候,并且g[i - 1] = 0表示前面没有负数,所以不可能组成负数g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;}else if (nums[i - 1] < 0){//当最后一个元素为负数的时候,并且g[i - 1] = 0表示前面没有负数,所以不可能组成正数f[i] = g[i - 1] == 0 ? 0 : g[i - 1]  + 1;g[i] = f[i - 1] + 1;}else {//处理为0的情况f[i] = 0;g[i] = 0;}ret = Math.max(ret,f[i]);}return ret;}

总结

当解决子数组问题时,动态规划是一个强大而智能的工具。通过将问题分解成更小的子问题并以递归的方式解决它们,动态规划可以高效地找到原始问题的解。在动态规划中,我们常常会遇到两种状态:一种是单独成一段,另一种是以 i 结尾的子数组。

枚举和动态规划是解决子数组问题的两种主要方法。枚举法需要考虑所有可能的子数组组合,然后比较它们以找到最优解。而动态规划则通过保存历史记录来避免不必要的重复计算,从而提高效率。

在动态规划中,常用的技巧包括前缀和和预处理。前缀和可以帮助我们快速求出数组中任意子数组的和,而预处理则可以在问题出现之前就对数据进行处理,以提高计算效率。

综上所述,动态规划是解决子数组问题的一种强大工具,通过合理利用枚举、动态规划、前缀和和预处理等技巧,我们可以高效地解决各种复杂的算法挑战,为问题提供简单明了的解决方案。

相关文章:

对于子数组问题的动态规划

前言 先讲讲我对于这个问题的理解吧 当谈到解决子数组问题时&#xff0c;动态规划(DP)是一个强大的工具&#xff0c;它在处理各种算法挑战时发挥着重要作用。动态规划是一种思想&#xff0c;它通过将问题分解成更小的子问题并以一种递归的方式解决它们&#xff0c;然后利用这些…...

Instal IIS on Windows Server 2022 Datacenter

和以往版本一样&#xff0c;没有什么不同&#xff0c;So easy&#xff01; WinR - ServerManager.exe 打开服务器管理器&#xff0c;点击【添加角色和功能】&#xff0c;选择自己想要的角色和功能。 一、开始之前&#xff1a;帮助说明&#xff0c;点击【下一步】&#xff1b;…...

飞天使-k8s知识点30-kubernetes安装1.28.0版本-使用containerd方式

文章目录 安装前准备containerd 配置内核参数优化安装nerdctl以上是所有机器全部安装开始安装初始化&#xff0c;这步骤容易出问题&#xff01; 安装前准备 内核升级包的md5,本人已验证&#xff0c;只要是这个md5值&#xff0c;放心升级 1ea91ea41eedb35c5da12fe7030f4347 ke…...

Oracle 误操作insert delete update 数据回滚

查询回滚数据 select * from tablename AS OF TIMESTAMP TO_TIMESTAMP(2023-12-29 10:29:00,yyyy-mm-dd hh24:mi:ss) where not exists (select 1 from tablename A where A.xh tablename.xh and A.TIME tablename.TIME); TO_TIMESTAMP(2023-12-29 10:29:00,yyyy-mm-dd h…...

Linux系统(CentOS)下安装配置 Nginx 超详细图文教程

一、下载并安装 1.打开nginx官网并点击右侧的download&#xff0c;Nginx官网下载地址 2.选择稳定版本 我放在/usr/local/nginx/下&#xff0c;新建文件夹 mkdir /usr/local/nginx/ 通过xftp传输到Linux的服务器上&#xff0c;这里方法不过多复述。 或者如果Linux联网&#xf…...

追求完美用户体验,从变量名设计的细节抓起

在一个安静的办公室里&#xff0c;卧龙和凤雏正坐在电脑前忙碌地工作着。阳光透过窗户洒在他们的脸上&#xff0c;映照出专注的神情。 “变量命名让人摸不着头脑&#xff0c;光看变量名很难搞清楚它的用途。”卧龙眉头紧皱&#xff0c;表情严肃地说道。 “哦&#xff1f;具体是…...

matlab实现K均值聚类

在MATLAB中实现聚类分析&#xff0c;可以使用MATLAB内置的聚类函数&#xff0c;如kmeans&#xff08;用于K均值聚类&#xff09;&#xff0c;linkage和cluster&#xff08;用于层次聚类&#xff09;&#xff0c;或者使用MATLAB的统计和机器学习工具箱中的其他函数。 以下是一个…...

详解BOM编程

华子目录 BOM编程window对象常见的window对象的属性常见的window对象的方法注意 history对象history对象的属性history对象的方法 screen 对象navigator 对象属性方法 location对象属性方法示例 BOM编程 JavaScript本质是在浏览器中运行&#xff0c;所以JavaScript提供了BOM&a…...

情感分类学习笔记(1)

文本情感分类&#xff08;二&#xff09;&#xff1a;深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…...

EtherCAT运动控制器Delta机械手应用

ZMC406硬件介绍 ZMC406是正运动推出的一款多轴高性能EtherCAT总线运动控制器&#xff0c;具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口&#xff0c;ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC406支持6轴运动控制&#xff0c;最多可扩展至32轴&#…...

物联网杀虫灯—新型的环保杀虫设备

型号推荐&#xff1a;云境天合TH-FD2S】物联网杀虫灯是一种新型环保杀虫设备&#xff0c;其中风吸式太阳能杀虫灯作为其一种特殊类型&#xff0c;展现了独特的工作原理和优势。 风吸式太阳能杀虫灯以太阳能电池板为电源&#xff0c;白天储存电源&#xff0c;晚上为杀虫灯提供电…...

加盟零食店的真是大冤种

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 我一朋友&#xff0c;在老家县城去年失业没事干&#xff0c;手里有一点钱但不多&#xff0c;就想着自己干点啥 。最后经多方打听考察&#xff0c;加盟了一个零食店&#xff0c;前前后后花去了近五六十万&#xff0c…...

力扣刷题--数组--第三天

今天再做两道二分查找的题目&#xff0c;关于二分查找的知识可看我前两篇博客。话不多说&#xff0c;直接开干&#xff01; 题目1&#xff1a;69.x 的平方根 题目详情&#xff1a;   给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。由于返回类型是整数&#…...

开源即时通讯IM框架 MobileIMSDK v6.5 发布

一、更新内容简介 本次更新为次要版本更新&#xff0c;进行了bug修复和优化升级&#xff08;更新历史详见&#xff1a;码云 Release Notes、Github Release Notes&#xff09;。 MobileIMSDK 可能是市面上唯一同时支持 UDPTCPWebSocket 三种协议的同类开源IM框架。轻量级、高…...

React 第二十七章 Hook useMemo

useMemo 函数可以用于缓存计算结果&#xff0c;以避免不必要的重复计算。 在React的函数组件中&#xff0c;当组件重新渲染时&#xff0c;函数组件内的所有代码都会重新执行。有些计算可能是非常消耗资源的&#xff0c;例如进行复杂的计算或进行网络请求。如果这些计算的结果在…...

自己写的爬虫小案例

网址&#xff1a;aHR0cDovL2pzc2NqZ3B0Lmp4d3JkLmdvdi5jbi8/dXJsPS92aWV3L3dvcmtpbmdVbml0L3dvcmtpbmdVbml0Lmh0bWw 这串代码能够爬取勘察单位企业的详细信息。 import requests import time import csv f open(勘察单位公司信息.csv,w,encodingutf-8,newline) csv_writer …...

Kafka 环境搭建和使用之单机模式详细教程

上一篇:Kakfa 简介及相关组件介绍 下一篇:Kafka 环境搭建之伪分布式集群详细教程 Kafka 环境搭建 Kafka的环境搭建可以根据不同的需求和场景采取不同的模式,主要包括以下几种: 单机模式(Standalone Mode): 在这种模式下,Kafka、Zookeeper 以及生产者和消费者都在同一…...

Xamarin.Android项目使用ConstraintLayout约束布局

Xamarin.AndroidX.ConstraintLayout Xamarin.Android.Support.Constraint.Layout Xamarin.AndroidX.ConstraintLayout.Solver Xamarin.AndroidX.DataBinding.ViewBinding Xamarin.AndroidX.Legacy.Support.Core.UI Xamarin.AndroidX.Lifecycle.LiveData ![在这里插入图片描述]…...

探索Java 18:未来技术趋势与革新之路

Java&#xff0c;作为一门历史悠久而又历久弥新的编程语言&#xff0c;始终站在技术发展的前沿&#xff0c;引领着软件开发的潮流。随着Java 18的发布&#xff0c;我们再次见证了这门语言的自我迭代与革新。本文将深入探讨Java 18带来的新特性、技术趋势&#xff0c;以及它如何…...

毕业论文怎么写? 推荐4个AI工具

写作这件事一直让我们从小学时期就开始头痛&#xff0c;初高中时期800字的作文让我们焦头烂额&#xff0c;一篇作文里用尽了口水话&#xff0c;拼拼凑凑才勉强完成。 大学时期以为可以轻松顺利毕业&#xff0c;结果毕业前的最后一道坎拦住我们的是毕业论文&#xff0c;这玩意不…...

JVM认识之垃圾收集算法

一、标记-清除算法 1、定义 标记-清除算法是最基础的垃圾收集算法。它分为标记和清除两个阶段。先标记出所有需要回收的对象&#xff08;即垃圾&#xff09;&#xff0c;在标记完成后再统一回收所有垃圾对象。 2、优点和缺点 优点&#xff1a;实现简单缺点&#xff1a; 可能…...

docker-compose部署gitlab

需要提前安装docker和docker-compose环境 参考&#xff1a;部署docker-ce_安装部署docker-ce-CSDN博客 参考&#xff1a;docker-compose部署_docker compose部署本地tar-CSDN博客 创建gitlab的数据存放目录 mkdir /opt/gitlab && cd mkdir /opt/gitlab mkdir {conf…...

Colab/PyTorch - 001 PyTorch Basics

Colab/PyTorch - 001 PyTorch Basics 1. 源由2. PyTorch库概览3. 处理过程2.1 数据加载与处理2.2 构建神经网络2.3 模型推断2.4 兼容性 3. 张量介绍3.1 构建张量3.2 访问张量元素3.3 张量元素类型3.4 张量转换&#xff08;NumPy Array&#xff09;3.5 张量运算3.6 CPU v/s GPU …...

翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习三

合集 ChatGPT 通过图形化的方式来理解 Transformer 架构 翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深…...

基于Seata实现分布式事务实现

Seata 是一个开源的分布式事务解决方案&#xff0c;它提供了高性能和简单易用的分布式事务服务。Seata 将事务的参与者分为 TC&#xff08;Transaction Coordinator&#xff09;、TM&#xff08;Transaction Manager&#xff09;和 RM&#xff08;Resource Manager&#xff09;…...

adss光缆是什么意思

adss光缆&#xff0c;adss光缆型号&#xff0c;adss光缆用途 什么是adss光缆 ADSS用于高压输电线路并利用电力系统输电塔干&#xff0c;整个光缆为非金属介质&#xff0c;自承悬挂于电力铁塔上的电力强度最小的位置。它运用于已建高压输电线路&#xff0c;具有安全性高&#…...

JavaScript异步编程——04-同源和跨域

同源和跨域 同源 同源策略是浏览器的一种安全策略&#xff0c;所谓同源是指&#xff0c;域名&#xff0c;协议&#xff0c;端口完全相同。 跨域问题的解决方案 从我自己的网站访问别人网站的内容&#xff0c;就叫跨域。 出于安全性考虑&#xff0c;浏览器不允许ajax跨域获取…...

出差——蓝桥杯十三届2022国赛大学B组真题

问题分析 该题属于枚举类型&#xff0c;遍历所有情况选出符合条件的即可。因为只需要派两个人&#xff0c;因此采用两层循环遍历每一种情况。 AC_Code #include <bits/stdc.h> using namespace std; string str;//选择的两人 bool ok(){if(str.find("A")!-1…...

UE5(射线检测)学习笔记

这一篇会讲解射线检测点击事件、离开悬停、进入悬停事件的检测&#xff0c;以及关闭射线检测的事件&#xff0c;和射线检测蓝图的基础讲解。 创建一个简单的第三人称模板 创建一个射线检测的文件夹RadiationInspection&#xff0c;并且右键蓝图-场景组件-命名为BPC_Radiation…...

语音识别的基本概念

语音识别的基本概念​​​​​​​ ​​​​​​​ 言语是一种复杂的现象。人们很少了解它是如何产生和感知的。天真的想法常常是语音是由单词构成的&#xff0c;而每个单词又由音素组成。不幸的是&#xff0c;现实却大不相同。语音是一个动态过程&#xff0c;没有明确区分的…...

不同类型网站比较及网站域名设计/app下载

文章目录KVM的vCPU调度算法的原理O(N)调度器O(1)调度器CFS调度器Xen Credit算法的原理CFS算法与Credit算法比较算法实现虚拟机兼容性实时性参考资料KVM的vCPU调度算法的原理 KVM的vCPU的整个生命周期都在Qemu线程的上下文中&#xff0c;在Kernel&#xff08;root模式&#xff…...

网站开发需会的课程/青岛网站建设公司电话

4.1 开发完第一个鸿蒙应用后&#xff0c;下面在了解一下完整的鸿蒙应用打包发布后应该是什么样子&#xff1a;一个完整的打包后应用结构如下图所示&#xff0c;这里我们先了解结构&#xff0c;具体怎么打包很简单只要前提是要签名!1. HAP的分类HAP又可分为entry和feature两种模…...

英国政府网站建设特点/3分钟搞定网站seo优化外链建设

单例模式 保证一个类只有一个实例&#xff0c;并且提供一个访问他的全局访问点 --《设计模式&#xff1a;可复用面向对象软件的基础》84页3.5节 在某些情况下我们需要一个类在任何情况下 只需要同一个实例并且提供一个访问该实例的方法 单例模式又分懒汉和饿汉模式 懒汉模式&a…...

江苏泰州建设局网站/友情链接买卖代理

在这篇文章里&#xff0c;你将学会什么是函数范式以及如何使用Python进行函数式编程。你也将了解列表推导和其它形式的推导。函数范式在命令式范式中&#xff0c;通过为计算机提供一系列指令然后执行它们来完成任务。在执行这些指令时&#xff0c;可以改变某些状态。例如&#…...

中国建设银官方网站/营销型网站建设运营

一、前期知识储备——后台功能 诺基亚Symbian操作系统特点&#xff1a;比起一般的手机&#xff0c;它可以支持后台功能。那个时候是能够一边打电话、一边听音乐&#xff0c;一边后台挂着QQ&#xff0c;非常酷。在后来的智能手机市场中&#xff0c;IOS系统刚开始是不支持后台的&…...

dede网站怎么做单页面/软件网站排行榜

点击上方“蓝色字”可关注我们&#xff01;暴走时评&#xff1a;IT业巨头富士通日前推出一项新的咨询服务&#xff0c;并表示该服务将在短短五天内实现“随时可用”的区块链最低可行产品研发。该服务起价9900欧元&#xff0c;内容包括从区块链技术基础入门课程、拟议用例评估再…...