【寻找one piece的算法之路】前缀和(一)

💐个人主页:初晴~

📚相关专栏:寻找one piece的刷题之路


什么是前缀和?

主要是通过预先计算数组或矩阵的前缀和,来快速查询子数组或子矩阵的和。这种算法可以用空间换时间,提高查询效率。

概念

给定一个数组 A,前缀和数组 PP 定义为:

P[i]=A[0]+A[1]+⋯+A[i]P[i]=A[0]+A[1]+⋯+A[i]

即 P[i]P[i] 是从数组开头到位置 ii 所有元素的和

计算前缀和

  1. 初始化:前缀和数组的第一个元素等于原数组的第一个元素,即 P[0]=A[0]。
  2. 迭代计算:对于每一个 i>0,计算 P[i]=P[i−1]+A[i]P[i]=P[i−1]+A[i]。

查询区间和

一旦前缀和数组构建完成,查询区间和的操作变得非常简单。如果要查询数组 AA 中从索引 ll 到索引 rr 的区间和,可以使用以下公式:

sum(l,r)=P[r]−P[l−1]sum(l,r)=P[r]−P[l−1]

注意,这里的 l−1 必须是非负的,因此查询的左端点 l 至少为 1(对于从 0 开始索引的数组,l 至少为 0)。

时间复杂度

  • 预处理时间复杂度:构建前缀和数组的时间复杂度为 O(n),其中 n 是数组的长度。
  • 查询时间复杂度:查询区间和的时间复杂度为 O(1),因为只需要一次简单的计算。

一、⼀维前缀和

题目链接

题目描述:

题目分析:

先准备一个数组dp【】来存储前缀和,dp【i】表示【1,i】区间内所有元素的和。我们可以通过一次遍历就求出前缀和数组,通过dp【i】=dp【i-1】+arr【i】来递推。

之后就可以通过前缀和数组快速求出“某一段区间”内所有元素的和

比如我们要查询区间【l,r】时,区间内元素和就为:dp【r】-dp【l-r】;

代码实现:

public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n=in.nextInt(),q=in.nextInt();long[] arr=new long[n+1];for(int i=1;i<=n;i++){arr[i]=arr[i-1]+in.nextInt();}for(int i=0;i<q;i++){int l=in.nextInt();int r=in.nextInt();System.out.println(arr[r]-arr[l-1]);}}
}

二、二维前缀和

题目链接

题目描述:

题目分析:

问题的关键在于我们能否搞出一个数组nums【】【】,让nums【i】【j】代表重【0,0】到【i,j】区域内所有元素的和。这样就有机会在O(1)的时间复杂度下快速查询出任意区域的元素和。

我们可以通过下图的方法建立前缀和数组,目的是为了避免繁琐的边界判定。这样下标从1开始填写,我们就能放心地使用【i-1】【j-1】下标的位置了:

我们可以将【0,0】到【i,j】区域划分为以下几块位置:

nums【i】【j】=红+篮+粉+绿

1、绿色区域的值就是arr【i】【j】的值

2、红+篮区域的值事实上就是【0,0】到【i-1,j】区域内的元素和,即nums【i-1】【j】

3、红+粉区域的值事实上就是【0,0】到【i,j-1】区域内的元素和,即nums【i】【j-1】

4、而红色区域的值事实上就是【0,0】到【i-1,j-1】区域内的元素和,即nums【i-1】【j-1】

这样我们就可以得到整个区域的元素和,就等于 红蓝+红粉-红+绿

也就可以得到 nums[i][j]=nums[i-1][j]+nums[i][j-1]-nums[i-1][j-1]+arr[i][j]

这样我们就可以通过一次遍历求出前缀和数组了。

求出前缀和数组后,我们还得想办法通过前缀和数组来查询计算出任意一块区域的元素和

类似的,我们可以划分出如下几个区域:

我们的目的就是求出绿色区域【x1,y1】到【x2,y2】区域内元素的和

由于我们已经求出前缀和了,于是我们可能得到一下区域的值:

1、红蓝粉绿 整个区域的元素和为nums【x2,y2】

2、红蓝 区域的元素和为 nums【x1-1】【y2】

3、红粉 区域的元素和为 nums【x2】【y1-1】

4、红色区域的元素和为 nums【x1-1】【y1-1】

这样,我们就可以得到绿色区域值等于 红蓝粉绿-红蓝-红粉+红

也就是 ans=nums[x2][y2]-nums[x2][y1-1]-nums[x1-1][y2]+nums[x1-1][y1-1]

代码实现:

public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n=in.nextInt(),m=in.nextInt(),q=in.nextInt();int[][] arr=new int[n+1][m+1];long[][] nums=new long[n+1][m+1];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){arr[i][j]=in.nextInt();}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){nums[i][j]=nums[i-1][j]+nums[i][j-1]-nums[i-1][j-1]+arr[i][j];}}for(int i=0;i<q;i++){int x1=in.nextInt();int y1=in.nextInt();int x2=in.nextInt();int y2=in.nextInt();System.out.println(nums[x2][y2]-nums[x2][y1-1]-nums[x1-1][y2]+nums[x1-1][y1-1]);}}
}

三、寻找数组的中心下标

题目链接

题目描述:

题目分析:

从中⼼下标的定义可知,除中⼼下标的元素外,该元素左边的「前缀和」等于该元素右边的「后缀
和」。
事实上,我们并不需要遍历两次分别求出前缀和 和 后缀和,可以通过一些技巧优化一下。
通过两个变量 l 和 r,分别该坐标 i 前后的 前缀和 和 后缀和。
  • 先遍历一遍数组,让 r 记录下整个数组的元素和。
  • 接着再进行一次遍历,让 r 减去当前遍历元素的值,这样,r 就能表示 i 坐标后的后缀和,
  • 然后比较此时 l 和 r 的值,如果相等,就声明找到目标位置了,直接返回;如果不相等,则让 l 加上当前遍历元素的值,这样 l 也就能表示遍历途中 的前缀和了
  • 重复上述步骤,就能解决题目要求了

代码实现:

class Solution {public int pivotIndex(int[] nums) {int n=nums.length,l=0,r=0;for(int num:nums){r+=num;}for(int i=0;i<n;i++){r-=nums[i];if(l==r)return i;l+=nums[i];}return -1;}
}


四、除自身以外数组的乘积

题目链接

题目描述:

题目分析:

注意题⽬的要求,不能使⽤除法,并且要在 O(N) 的时间复杂度内完成该题。那么我们就不能使
⽤暴⼒的解法,以及求出整个数组的乘积,然后除以单个元素的⽅法。
继续分析,根据题意,对于每⼀个位置的最终结果 ret[i] ,它是由两部分组成的:
  • nums[0] * nums[1] * nums[2] * ... * nums[i - 1]
  • nums[i + 1] * nums[i + 2] * ... * nums[n - 1]
于是,我们可以利⽤前缀和的思想,使⽤两个数组 qian 和 hou,分别处理出来两个信息:
  • qian 表⽰:i 位置之前的所有元素,即 [0, i - 1] 区间内所有元素的前缀乘积,
  • hou 表⽰: i 位置之后的所有元素,即 [i + 1, n - 1] 区间内所有元素的后缀乘积
然后再处理最终结果。

代码实现:

class Solution {public int[] productExceptSelf(int[] nums) {int n=nums.length;int[] answer=new int[n];int[] qian=new int[n],hou=new int[n]; qian[0]=1;hou[n-1]=1;for(int i=1;i<n;i++){qian[i]=qian[i-1]*nums[i-1];}for(int i=n-2;i>=0;i--){hou[i]=hou[i+1]*nums[i+1];}for(int i=0;i<n;i++){answer[i]=qian[i]*hou[i];}return answer;}
}

那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode 3217 从链表中移除在数组中的结点

1.题目要求: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后&#xff0c;返回修改后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a; nums [1,2,3], head [1,2,3,4,5] 输出&#xff1a; [4,5] 解释&#xff1a; 移除数值…

PCL点云处理之求法向量

求法向量干什么&#xff1f;将点渲染成面 1、一个点垂直于一个曲线的切线叫法线 2、在点云中取一块区域&#xff0c;用最小二乘将区域中的点云拟合成一个面&#xff08;贴合在曲面上的一个切面&#xff09;在相近的区域计算出n个这样的面&#xff0c;用这个面求出法向量&#…

最新开源:智源BGE登顶Hugging Face月度榜!北大快手开源Pyramid Flow!Rhymes AI发布首款开源多模态AI模型Aria!

文章目录 1. 国产AI模型登顶全球TOP 1&#xff01;智源BGE下载破亿成Hugging Face月榜冠军2. 北大&快手开源视频生成模型Pyramid Flow&#xff0c;1分钟生成5秒视频3. Rhymes AI发布首款开源多模态AI模型Aria&#xff0c;性能超越GPT-4o mini4. Mistral AI发布 Pixtral-12B…

华为 静态路由和bfd 侦测的实验

实验要求 sw1 上业务地址192.168.1.1/24 SW3 业务地址192.168.2.1/24 正常情况下走主链路&#xff0c;不正常的情况下走备份链路 2 配置 这是基本地址配置 开启了bfd 本端地址为 10.1.1.1 对端地址是10.1.1.2 关键是discrimination 分辨参数 …

【JavaScript】LeetCode:61-65

文章目录 61 课程表62 实现Trie&#xff08;前缀树&#xff09;63 全排列64 子集65 电话号码的字母组合 61 课程表 Map BFS拓扑排序&#xff1a;将有向无环图转为线性顺序。遍历prerequisites&#xff1a;1. 数组记录每个节点的入度&#xff0c;2. 哈希表记录依赖关系。n 6&a…

基于深度学习的细粒度图像分析综述【翻译】

&#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 &#x1f389; 声明: 作为全网 AI 领域 干货最多的博主之一&#xff0c;❤️ 不负光阴不负卿 ❤️ 文章目录 基础信息0 摘要1 INTRODUCTION2 识别与检索 RECOGNITION VS. RETRIEVAL3 问题和…

牛客SQL练习详解 06:综合练习

牛客SQL练习详解 06&#xff1a;综合练习 SQL34 统计复旦用户8月练题情况SQL35 浙大不同难度题目的正确率SQL39 21年8月份练题总数 叮嘟&#xff01;这里是小啊呜的学习课程资料整理。好记性不如烂笔头&#xff0c;今天也是努力进步的一天。一起加油进阶吧&#xff01; SQL34 统…

Python100道新手练习题(附答案)

基础语法 1.打印 “Hello, World!” print("Hello, World!")2.定义一个变量并打印其值 message "Hello, Python!" print(message)3.定义两个整数变量并计算它们的和 a 5 b 3 sum a b print(sum)4.使用条件语句判断一个数是否为正数 num 10 if n…

初知C++:AVL树

文章目录 初知C&#xff1a;AVL树1.AVL树的概念2.AVL树的是实现2.1.AVL树的结构2.2.AVL树的插入2.3.旋转2.4.AVL树的查找2.5.AVL树平衡检测 初知C&#xff1a;AVL树 1.AVL树的概念 • AVL树是最先发明的自平衡⼆叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性…

node.js服务器基础

node.js的事件循环 node.js是基于事件驱动的&#xff0c;通常在代码中注册想要等待的事件&#xff0c;设定好回调函数&#xff0c;当事件触发的时候就会调用回调函数。如果node.js没有要处理的事件了&#xff0c;那整个就结束了;事件里面可以继续插入事件&#xff0c;如果有事…

低代码开发技术:驱动MES系统创新与制造业数字化转型的融合之路

低代码开发与生产管理MES系统的融合&#xff0c;是当今制造业数字化转型的一个重要趋势。以下是对这一融合现象的详细分析&#xff1a; 一、低代码开发的概念与特点 低代码开发是一种通过图形化界面和预构建模块来简化应用程序开发过程的方法。它允许开发人员使用拖放组件和最…

接口多继承与子类继承多接口时的冲突问题,方法冲突与变量冲突.....

&#x1f680; 个人简介&#xff1a;某大型国企资深软件开发工程师&#xff0c;信息系统项目管理师、CSDN优质创作者、阿里云专家博主&#xff0c;华为云云享专家&#xff0c;分享前端后端相关技术与工作常见问题~ &#x1f49f; 作 者&#xff1a;码喽的自我修养&#x1f9…

JavaScript 第7章:字符串处理

第7章&#xff1a;字符串处理 在 JavaScript 中&#xff0c;字符串是一个非常常用的数据类型&#xff0c;用于表示文本信息。JavaScript 提供了许多内置的方法来处理字符串&#xff0c;包括操作、搜索、替换和格式化等。 一、字符串操作方法 1. charAt charAt(index) 方法返…

支票欺诈检测AI系统

这是我们 LLM Makerspace 活动的记录摘要&#xff0c;我们使用经过微调的 LLM 构建了一个支票欺诈检测和解释 AI 系统。 那么&#xff0c;支票到底是什么&#xff1f;它们本质上是一种汇款&#xff0c;你将金额写在一张纸上并将其交给某人。它被视为法定货币和服务付款。作为一…

光明乳业乳品四厂勇闯TPM世界级奖终审,开创中国乳品行业新纪元

近日&#xff0c;中国乳品行业的标志性事件在光明乳业乳品四厂隆重上演&#xff0c;该厂迎来了TPM&#xff08;全面生产维护&#xff09;世界级奖项的终审评审&#xff0c;这不仅是光明乳业发展历程中的重大突破&#xff0c;也是中国乳品行业首次冲击该领域最高荣誉——TPM世界…

华为面试就这?00后直接拿下20K的offer...

先说一下我的情况&#xff0c;某不知名211本计算机毕业&#xff0c;之前在深圳那边做了大约半年多少儿编程老师&#xff0c;之后内部平调回长沙这边&#xff0c;回来之后发现有点难&#xff0c;这边可能是业绩难做&#xff0c;虚假承诺很厉害&#xff0c;要给那些家长虚假承诺去…

mac 桌面版docker no space left on device

报错信息 docker pull镜像时报&#xff1a; failed to register layer: Error processing tar file(exit status 1): write /home/admin/oceanbase_bak/bin/observer: no space left on device 解决 增加 docker 虚拟磁盘大小。 调整完点击重启即可。

Etsy店铺总是被封?看看这些替代平台!

对于创意商家而言&#xff0c;Etsy是一个充满机遇的电商平台。然而&#xff0c;Etsy平台政策过于苛刻&#xff0c;许多卖家的店铺频繁遭遇封禁&#xff0c;辛苦建立的客户基础瞬间化为乌有。本文将为您介绍几个值得一试的Etsy替代平台&#xff0c;帮助您分散经营风险&#xff0…

匹配全国地址的正则表达式工具类

正则表达式&#xff0c;匹配全国五级地址工具类&#xff0c;可以直接放在项目中使用~ 1级&#xff1a;国 &#xff08;可忽略不填&#xff09; 2级&#xff1a;**省、**自治区、**直辖市、**特别行政区、&#xff08;四个直辖市可忽略不填&#xff09; 3级&#xff1a;**市、**…

pytest + yaml 框架 - 支持pytest-repeat插件重复执行用例

平常在做功能测试的时候&#xff0c;经常会遇到某个模块不稳定&#xff0c;偶然会出现一些bug&#xff0c;对于这种问题我们会针对此用例反复执行多次&#xff0c;最终复现出问题来。 自动化运行用例时候&#xff0c;也会出现偶然的bug&#xff0c;可以针对单个用例&#xff0…