Java前缀和算法
一.什么是前缀和算法
通俗来讲,前缀和算法就是使用一个新数组来储存原数组中前n-1个元素的和(如果新数组的当前元素的下标为n,计算当前元素的值为原数组中从0到n-1下标数组元素的和),可能这样讲起来有点抽象,我们举一个例子对其进行说明:给定一个数组nums[],我们创建一个大小为nums.length+1的求和数组sums[],对sum[]数组进行遍历:sum[i]=nums[0]+nums[1]+...+nums[i-1](相当于nums[i-1]+sum[n-1]),比如存在int[]nums={1,2,3,4},对应的前缀和数组的值为sum={0,1,3,6,10}
二.前缀和算法相对于滑动窗口具有哪些不可替代的优势及前缀和算法对算法题目的优化策略
我们在前面讲述的前缀和算法,可能很多小伙伴对其的特点也有所察觉:发现其与我们上一节讲到的滑动窗口有些类似,我们结合下面这道题目,讲讲前缀和算法对于如下这种题目而言,具有怎样的解题优势

对于滑动窗口一般的解题思路如下:如果当前窗口的元素大于预期条件的元素时,我们将窗口的左指针向右移动;如果当前窗口的元素小于预期条件的元素时,我们将窗口的右指针向右移动,扩大窗口,但是对于上面的题目中,测试用例中存在负数的情况,那么对于窗口中出现了负数这种情况,我们是该将窗口右移直到满足条件还是将窗口左移直到剔除这个负数呢?这明显超出了我们之前规定的对于使用滑动窗口的条件,这也就是滑动窗口的局限性,而根据我们对于上文中对前缀和算法的描述,前缀和算法并不规定其中的元素一定要是正数或者负数,我们只是将其中的元素进行相加,而前缀和算法对于解决这种题目可谓大显身手。
除此之外,我们讲一下前缀和算法的应用相对于我们使用暴力解法具有怎样的优化:如果不创建一个新的数组来存储前n个元素的和,那么此时我们每次求和时,都需要从头到尾将元素和全部求一遍,对于一维数组,时间复杂度达到了O(n),但是如果我们将前面元素和进行存储,每次求和只需要调用我=我们前缀和数组中的元素,时间复杂度只有O(1),大大降低了时间复杂度;同理,对于二维数组而言,他可以将O(n^2)的时间复杂度降至O(1).
三.前缀和算法的模板代码
对于前缀和算法,一般存在一维的前缀和与二维的前缀和这样两种不同的算法模板,关于前缀和算法的模板,我们使用preSum来计算数组的前缀和,preSum[i]代表着前i个前i-1个数组元素的和;对于二维数组,preSum[i][j]则代表着行为 0到i-1,列为0-j-1元素的和
一维前缀和模板
如下是一维前缀和算法的模板代码:

public int[] preSum(int[] nums) {int[] preSum = new int[nums.length+1];for (int i = 1; i < =nums.length; ++i) {preSum[i] = preSum[i - 1] + nums[i-1];}return preSum;}
二维前缀和模板
如下是二维前缀和的算法模板:对于二维的前缀和模板,是对一维前缀和模板的扩展,但在本质上是完全一致的,我们来描述有关二维数组的前缀和的模板:

我们给出这样一个图示:
对于二维数组的前缀和而言,表达式可以表述为这样:
每一个二维数组中的单位元素,相等于绿-澄-蓝+粉,我们同样给出一个二维数组,presum[nums.length+1][nums[0].length+1],presum[n][n]则代表0-n-1行,0-n-1列的数据总和 、
其模板表达式如下:
class NumMatrix {// 定义:preSum[i][j] 记录 matrix 中子矩阵 [0, 0, i-1, j-1] 的元素和private int[][] preSum;public NumMatrix(int[][] matrix) {int m = matrix.length, n = matrix[0].length;if (m == 0 || n == 0) return;// 构造前缀和矩阵preSum = new int[m + 1][n + 1];for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {// 计算每个矩阵 [0, 0, i, j] 的元素和preSum[i][j] = preSum[i-1][j] + preSum[i][j-1] + matrix[i - 1][j - 1] - preSum[i-1][j-1];}}}// 计算子矩阵 [x1, y1, x2, y2] 的元素和public int sumRegion(int x1, int y1, int x2, int y2) {// 目标矩阵之和由四个相邻矩阵运算获得return preSum[x2+1][y2+1] - preSum[x1][y2+1] - preSum[x2+1][y1] + preSum[x1][y1];}
}
除了完全的一维和二维的前缀和算法之外,前缀和算法的题目通常会与hash等数据结构组合出题
四.关于前缀和算法的经典题目练习
1.区域和检索 - 数组不可变力扣
力扣题目描述

解题思路
这是一个完全意义上的前缀和算法的题目,或者说这是一个书写前缀和算法模板的题目,对于这道题,我们直接使用我们前面使用的前缀和算法的模板即可:创建nums.length+1长度的presum[],对于presum[n],存储的是前n-1个元素的和,每次求和时直接使用presum中的元素即可。
实例代码
我们给出实例代码:
class Solution {public int subarraySum(int[] nums, int k) {//单纯使用前缀和,无法判别从哪里进行区分,这时我们需要将符合条件的数值直接存入map,再次需要时直接拿来使用即可int count=0;//记录最终的结果int pre=0;//记录前缀和//创建mapHashMap<Integer,Integer>map=new HashMap<>();//如果是pre-target=0,代表从0开始刚好满足条件要求map.put(0,1);for(int i=0;i<nums.length;++i){pre+=nums[i];if(map.containsKey(pre-k)){count+=map.get(pre-k);}//将当前pre加入map.put(pre,map.getOrDefault(pre,0)+1);}return count;}
}
class NumArray {//本题使用前缀和算法,将使劲复杂度从O(n)降至O(1)private int[]preNums;public NumArray(int[] nums) {preNums=new int[nums.length+1];//循环时创建前缀和for(int i=1;i<preNums.length;++i){preNums[i]=preNums[i-1]+nums[i-1];}}public int sumRange(int left, int right) {return preNums[right+1]-preNums[left];}
}
2.和为 k 的子数组 力扣
题目描述

解题思路
这道题就是对我们一维数组前缀和算法的扩展了,它不仅仅使用简单的前缀和数组进行存储数组的前缀和,他同样需要使用hash表进行元素的记录和存储,这是一道前缀和数组和哈希表进行融合的题目,具体的解题思路如下:我们对于这道题目而言,难点在于对于简单的前缀和数组而言,我们无法判断从哪个地方进行断开(无法判断从那个地方作为起点,哪个地方作为终点是符合条件的),因为我们在此基础上使用哈希表,哈希表中存储的是当前元素为基准的前缀和与target之间的差距,如果差距为0(恰好满足)或者当前差距等于其前面元素的前缀和(如果前面元素的前缀和为4,此时前缀和-target=4 :前缀和比我们需要的和的值大4,刚好与前面的值进行抵消),这种也是符合条件的。
图示如下:
实例代码
我们给出实例代码
class Solution {public int subarraySum(int[] nums, int k) {//单纯使用前缀和,无法判别从哪里进行区分,这时我们需要将符合条件的数值直接存入map,再次需要时直接拿来使用即可int count=0;//记录最终的结果int pre=0;//记录前缀和//创建mapHashMap<Integer,Integer>map=new HashMap<>();//如果是pre-target=0,代表从0开始刚好满足条件要求map.put(0,1);for(int i=0;i<nums.length;++i){pre+=nums[i];if(map.containsKey(pre-k)){count+=map.get(pre-k);}//将当前pre加入map.put(pre,map.getOrDefault(pre,0)+1);}return count;}
}
3.二维子矩阵的和力扣
题目描述

解题思路
这道题正是我们上面讲述的关于二维数组求前缀和的典型例题,我们在上面模板的基础上进行思路的讲解:对于红框内的元素和,等于绿框元素-蓝框-红框+黑框(其中蓝框和红框中也有黑框的部分,但是被颜色覆盖了),在此之前,我们首先要将元素进行初始化,初始化的过程相当于对元素进行分割的逆过程:单位元素加上两边的元素再减去重复的元素


实例代码
class NumMatrix {//创建二维的数组和private int[][]preNums;public NumMatrix(int[][] matrix) {preNums=new int[matrix.length+1][matrix[0].length+1];//创建并遍历for(int i=1;i<preNums.length;++i){for(int j=1;j<preNums[0].length;++j){preNums[i][j]=preNums[i][j-1]+preNums[i-1][j]-preNums[i-1][j-1]+matrix[i-1][j-1];}}}public int sumRegion(int row1, int col1, int row2, int col2) {return preNums[row2+1][col2+1]-preNums[row2+1][col1]-preNums[row1][col2+1]+preNums[row1][col1];}
}
4.除自身以外数组的乘积力扣
题目描述

解题思路
这道题目的解题思路相对而言比较巧妙,它将前缀和拓展为前缀积,而除了本身元素之外的其他元素的和,则恰好符合前缀积中premul[i]*lastmul[i]的定义,所以直接定义前缀后缀积进行元素的相乘即可
实例代码
class Solution {public int[] productExceptSelf(int[] nums) {//解题思路:通过前缀积和后缀积进行相乘,最终的结果就是除了nums[i]之外的相乘结果,需要注意的是:需要对前后缀积的含义进行一定的改变//定义前缀积int[]pre=new int[nums.length];//定义后缀积int[]last=new int[nums.length];//初始化并相乘pre[0]=1;for(int i=1;i<nums.length;++i){pre[i]=nums[i-1]*pre[i-1];}last[nums.length-1]=1;for(int i=nums.length-2;i>=0;--i){last[i]=last[i+1]*nums[i+1];}int[]res=new int[nums.length];//进行最后的结果返回for(int i=0;i<nums.length;++i){res[i]=pre[i]*last[i];}return res;}
}
相关文章:
Java前缀和算法
一.什么是前缀和算法 通俗来讲,前缀和算法就是使用一个新数组来储存原数组中前n-1个元素的和(如果新数组的当前元素的下标为n,计算当前元素的值为原数组中从0到n-1下标数组元素的和),可能这样讲起来有点抽象࿰…...
pico 的两个双核相关函数的延时问题
pico高级API函数中, multicore_fifo_pop_timeout_us 和 multicore_fifo_push_timeout_us 的延时参数, 如修改为500微秒以上时,其延时似乎远远超过设定值,其反馈速度似乎被主核的交互所左右 ,而修改为200以下时&#x…...
Doxygen源码分析: QCString类依赖的qstr系列C函数浅析
2023-05-20 17:02:21 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. doxygen 版本2. QCString 类简介3. qstr 系列函数浅析qmemmove()qsnprintfqstrdup()qstrfree()qstrlen()qstrcpy()qstrncpy()qisempty()qstrcmp()qstrncmp()qisspace()qstr…...
华为OD机试之一种字符串压缩表示的解压(Java源码)
一种字符串压缩表示的解压 题目描述 有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。 例如:字符串“aaabbccccd”经过压缩成为字符串“…...
Microsoft Project Online部署方案
目录 一、前言 二、Microsoft Project Online简介 三、Microsoft Project Online的优势 1、云端部署 2、多设备支持...
飞浆AI studio人工智能课程学习(3)-在具体场景下优化Prompt
文章目录 在具体场景下优化Prompt营销场景办公效率场景日常生活场景海报背景图生成办公效率场景预设Prompt 生活场景中日常学习Prompt: 给写完的代码做文档 将优质Prompt模板化Prompt 1:Prompt 1:Prompt 2步骤文本过长而导致遗失信息的示例修改后 特殊示例 如何提升安全性主要目…...
企业工程行业管理系统源码-专业的工程管理软件-提供一站式服务
Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目显示1…...
Ehcache 整合Spring 使用页面、对象缓存
Ehcache在很多项目中都出现过,用法也比较简单。一般的加些配置就可以了,而且Ehcache可以对页面、对象、数据进行缓存,同时支持集群/分布式缓存。如果整合Spring、Hibernate也非常的简单,Spring对Ehcache的支持也非常好。EHCache支…...
Spring Cloud中的服务路由与负载均衡
Spring Cloud中的服务路由与负载均衡 一、服务路由1. 服务发现2. 服务注册3. 服务消费4. 服务提供5. 服务路由实现 二、负载均衡1. 负载均衡的概念2. 负载均衡算法3. 负载均衡实现4. 负载均衡策略5. 使用Spring Cloud实现负载均衡 三、服务路由与负载均衡的集成1. 集成背景2. 集…...
rails routes的使用
Rails routes 是用于确定应该将请求发送到哪个控制器和操作的一种机制。在 Rails 应用程序中,可以通过定义路由来映射 URL 到控制器操作。可以使用 rails routes 命令查看当前应用程序中定义的所有路由。 以下是一些常见的用法: 查看所有路由ÿ…...
Linux基础内容(21)—— 进程消息队列和信号量
Linux基础内容(20)—— 共享内存_哈里沃克的博客-CSDN博客 目录 1.消息队列 1.定义 2.操作 2.信号量 1.定义 2.细节 3.延申 4.操作 3.IPC的特点共性 1.消息队列 1.定义 定义:是操作系统提供的内核级队列 2.操作 msgget:…...
STM32实现基于RS485的简单的Modbus协议
背景 我这里用STM32实现,其实可以搬移到其他MCU,之前有项目使用STM32实现Modbus协议 这个场景比较正常,很多时候都能碰到 这里主要是Modbus和变频器通信 最常见的是使用Modbus实现传感器数据的采集,我记得之前用过一些传感器都…...
springboot服务端接口公网远程调试 - 实现HTTP服务监听【端口映射】
文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…...
zabbix监控之javasnmp自定义监控
1、客户端开启 java jmxremote 远程监控功能 上传 tomcat 软件包到 /opt 目录中 cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mv apache-tomcat-9.0.16 /usr/local/tomcat #配置 java jmxremote 远程监控功能 vim /usr/local/tomcat/bin/catalina.sh ...... #位置在 cygw…...
Inertial Explorer处理pospac数据总结
Inertial Explorer处理pospac数据的过程包括:1)从pospac提取出gps数据和imu数据;2)gps数据转成rinex格式;3)imu数据转成imr格式;4)IE对gps数据进行PPP解算;5)紧耦合融合解…...
tps和qps的区别是什么?怎么理解
区别:QPS指的是“每秒查询率”;而TPS指的是“事务数/秒”。理解:Tps即每秒处理事务数,对于一个页面的一次访问,形成一个Tps;而一次页面请求,可能产生多次对服务器的请求,服务器对这些…...
【Java系列】深入解析枚举类型
序言 即便平凡的日子仿佛毫无波澜,但在某个特定的时刻,执着的努力便会显现出它的价值和意义。 希望这篇文章能让你不仅有一定的收获,而且可以愉快的学习,如果有什么建议,都可以留言和我交流 问题 思考一下这寄个问题&a…...
网络原理(五):IP 协议
目录 认识IP 地址 子网掩码 作用 动态分配IP 地址 NAT 机制 认识MAC地址 MAC地址如何工作 网络设备和相关技术 集线器:转发所有端口 交换机:MAC地址转换表转发 主机&路由器:ARP缓存表ARP寻址 路由器:路由NAPT 数…...
MySQL---空间索引、验证索引、索引特点、索引原理
1. 空间索引 MySQL在5.7之后的版本支持了空间索引,而且支持OpenGIS几何数据模型 空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是: 类型 含义 说明 Geometry 空间数据 任何一种空间类型 Poi…...
选择合适的 MQTT 云服务:一文了解 EMQX Cloud Serverless、Dedicated 与 BYOC 版本
引言 EMQX Cloud 是基于 EMQX Enterprise 构建的一款全托管云原生 MQTT 消息服务。为了满足不同客户的需求,EMQX Cloud 提供了三种版本供客户选择:Serverless 版、专有版和 BYOC 版。 本文将简要介绍这三个版本的核心区别,并通过三个用户故…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

