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

LeetCode-刷题记录-前缀和合集(本篇blog会持续更新哦~)

一、前缀和(Prefix Sum)算法概述

前缀和算法通过预先计算数组的累加和,可以在常数时间内回答多个区间和相关的查询问题,是解决子数组和问题中的重要工具。

在这里插入图片描述

它的基本思想是通过预先计算和存储数组的前缀和,可以在 O(1) 的时间复杂度内计算任意子数组的和。

在这里插入图片描述

  1. 定义
    • 对于数组 nums,其前缀和 prefix[i] 定义为从数组起始位置到第 i 个元素的累加和。

在这里插入图片描述

  • 具体公式:prefix[i] = nums[0] + nums[1] + ... + nums[i]
  1. 计算方法
    • 首先,创建一个额外的数组或哈希表,用来存储每个位置的前缀和。
    • 通过一次遍历数组,依次计算并填充这个数组或哈希表。

在这里插入图片描述

  1. 应用
    • 快速计算子数组和:通过前缀和,可以快速计算任意子数组的和。例如,子数组 nums[l...r] 的和可以通过 prefix[r] - prefix[l-1] 来计算,其中 lr 分别是子数组的左右边界。

在这里插入图片描述

  • 解决相关问题:例如,最大子数组和、和为特定值的子数组个数等问题,都可以通过前缀和算法高效解决。

在这里插入图片描述


二、前缀和习题合集

1. LeetCode 930 和相同的二元子数组

在这里插入图片描述

  • 思路:

假设原数组的前缀和数组为 sum,且子数组 (i,j] 的区间和为 goal,那么 sum[j]−sum[i]=goal。因此我们可以枚举 j ,每次查询满足该等式的 i 的数量。

用哈希表记录每一种前缀和出现的次数,假设我们当前枚举到元素 nums[j],我们只需要查询哈希表中元素 sum[j]−goal 的数量即可,这些元素的数量即对应了以当前 j 值为右边界的满足条件的子数组的数量。

  • pre[j] - pre[i]= goal —> pre[i] = pre[j] - goal

  • 如果存在前缀和为 pre[j] - goal(也就是pre[i])

  • 说明从某个位置 j 到当前位置 i 的子数组和为 goal

最后这些元素的总数量即为所有和为 goal 的子数组数量。

  • 代码:

class Solution {public int numSubarraysWithSum(int[] nums, int goal) {int n = nums.length; // 数组的长度Map<Integer,Integer> map = new HashMap<>(); // 使用哈希表来记录前缀和的出现次数int pre_J = 0; // 初始前缀和为0int ans = 0; // 计数器,用来记录符合条件的子数组个数for (int i = 0; i < n; i++) {map.put(preJ, map.getOrDefault(pre_J, 0) + 1); // 更新前缀和为 preJ 的出现次数pre_J += nums[i]; // 计算当前位置的前缀和//pre[j] - pre[i]= goal //pre[i] = pre[j] - goal// 计算满足条件的子数组个数// 如果存在前缀和为 pre[j] - goal(也就是pre[i])//说明从某个位置 j 到当前位置 i 的子数组和为 goalans += map.getOrDefault(pre_J - goal, 0);}return ans; // 返回符合条件的子数组个数}
}

2. LeetCode 560 和为K的子数组

在这里插入图片描述

  • 这里咋一看好像是可以用滑动窗口哈 ,但是发现数据里有负数。因为nums[i]可以小于0,也就是说右指针j向后移1位不能保证区间会增大,左指针i向后移1位也不能保证区间和会减小。

  • 思路 : 同上一题类似

前缀和 + 哈希

class Solution {public static int subarraySum(int[] nums, int k) {int n = nums.length; // 获取数组长度Map<Integer,Integer> map = new HashMap<>(); // 创建哈希表,用于存储前缀和及其出现次数int sum = 0; // 初始化前缀和为0int ans = 0; // 初始化结果为0map.put(sum,1); // 将初始的前缀和0放入哈希表,并设其出现次数为1// 遍历数组for(int num : nums){sum += num; // 计算当前位置的前缀和// 如果哈希表中存在前缀和为sum-k的项,则说明存在和为k的子数组 sum - (sum-k) = kif(map.containsKey(sum - k)){ans += map.get(sum - k); // 更新结果,累加前缀和为sum-k的子数组数量}map.put(sum, map.getOrDefault(sum, 0) + 1); // 更新哈希表,将当前前缀和放入,并更新出现次数}return ans; // 返回结果}
}
  • 初始时,将前缀和为 0 放入哈希表 map 中,表示在初始状态下存在一个前缀和为 0 的情况,出现次数为 1。

  • 如果 map 中存在 sum - k,则说明从之前的某个位置到当前位置的子数组的和为 k。这是因为 sum - (sum - k) = k

  • 如果存在这样的前缀和,则将该前缀和的出现次数累加到 ans 中。


3. LeetCode 523 连续的子数组和

在这里插入图片描述

在这里插入图片描述

  • 这里要用到数学知识——同余定理

在这里插入图片描述

  1. 前缀和的定义:preSum[i] 表示 nums 数组从 0 到 i 的元素之和。

    • 如果存在一个子数组 nums[j..i] (j < i),其和是 k 的倍数,则 preSum[i] - preSum[j-1] 必须是 k 的倍数。
  2. 利用余数的性质(同余定理)

    • 如果 preSum[i]preSum[j-1]k 取余得到相同的结果,即 (preSum[i] - preSum[j-1]) % k == 0,则存在这样的子数组。
    • a%k = b%k ,则 (a-b)%k =0 满足条件

在这里插入图片描述

  1. 使用哈希表记录余数: 使用哈希表来记录每个余数第一次出现的位置。

class Solution {public boolean checkSubarraySum(int[] nums, int k) {int n = nums.length;int[] pre = new int[n + 1];for (int i = 1; i <= n; i++) {pre[i] = pre[i - 1] + nums[i - 1]; // 计算前缀和}Set<Integer> set = new HashSet<>();for (int i = 2; i <= n; i++) {set.add(pre[i - 2] % k); // 将前缀和前两项的同余结果加入集合if (set.contains(pre[i] % k)) return true; // 如果当前前缀和对k取模的结果在集合中已经存在,说明找到了符合条件的子数组}return false; // 如果遍历完没有找到符合条件的子数组,返回false}
}

4. LeetCode 724 寻找数组的中心下标

在这里插入图片描述

  • 前缀和思想

法一:

class Solution {public static int pivotIndex(int[] nums) {int n = nums.length;int[] sumLeft = new int[n]; // 用于存储每个索引位置左侧元素之和int[] sumRight = new int[n]; // 用于存储每个索引位置右侧元素之和sumLeft[0] = 0; // 初始化左侧和数组的第一个元素为0(因为第一个元素左侧没有元素)sumRight[n - 1] = 0; // 初始化右侧和数组的最后一个元素为0(因为最后一个元素右侧没有元素)int sum1 = 0; // 用于计算累积的左侧和int sum2 = 0; // 用于计算累积的右侧和// 计算每个索引位置左侧的累积和for (int i = 0; i < n; i++) {sum1 += nums[i];sumLeft[i] = sum1;}// 计算每个索引位置右侧的累积和for (int i = n - 1; i >= 0; i--) {sum2 += nums[i];sumRight[i] = sum2;}// 遍历数组,找到第一个满足左侧和等于右侧和的索引位置for (int i = 0; i < n; i++) {if (sumLeft[i] == sumRight[i]) {return i;}}// 如果没有找到满足条件的索引,返回-1return -1;}
}

法二:

class Solution {public static int pivotIndex(int[] nums) {int totalSum = 0; // 计算整个数组的和for (int num : nums) {totalSum += num;}int leftSum = 0; // 左侧和的初始值为0for (int i = 0; i < nums.length; i++) {int rightSum = totalSum - leftSum - nums[i]; // 右侧和等于总和减去左侧和和当前数字if (leftSum == rightSum) {return i; // 如果左右两侧和相等,则返回当前索引作为轴心索引}leftSum += nums[i]; // 更新左侧和,将当前数字累加到左侧和中}return -1; // 如果遍历完整个数组都没有找到轴心索引,则返回-1表示不存在}
}

5. LeetCode 238 除自身以外数组的乘积

在这里插入图片描述

  • 思路 :前缀积 + 后缀积 (左右乘积列表)

我们不必将所有数字的乘积除以给定索引处的数字得到相应的答案,而是利用索引左侧所有数字的乘积和右侧所有数字的乘积(即前缀与后缀)相乘得到答案。

注意这里有一个细节就是要除了自己,所以在累乘的时候,要在当前位置保存 左侧 或者 右侧 (不包含自己)。

前积乘后积,先存后乘避开自己

class Solution {public int[] productExceptSelf(int[] nums) {int n= nums.length;// L 和 R 分别表示左右两侧的乘积列表int[] L = new int[n];int[] R = new int[n];int[] answer = new int[n];// L[i] 为索引 i 左侧所有元素的乘积// 对于索引为 '0' 的元素,因为左侧没有元素,所以 L[0] = 1L[0] = 1;for (int i = 1; i < n; i++) {L[i] = nums[i - 1] * L[i - 1];}// R[i] 为索引 i 右侧所有元素的乘积// 对于索引为 'n-1' 的元素,因为右侧没有元素,所以 R[length-1] = 1R[n- 1] = 1;for (int i = n- 2; i >= 0; i--) {R[i] = nums[i + 1] * R[i + 1];}// 对于索引 i,除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积for (int i = 0; i < n; i++) {answer[i] = L[i] * R[i];}return answer;}
}

class Solution {public int[] productExceptSelf(int[] nums) {int length = nums.length;int[] answer = new int[length];// answer[i] 表示索引 i 左侧所有元素的乘积// 因为索引为 '0' 的元素左侧没有元素, 所以 answer[0] = 1answer[0] = 1;for (int i = 1; i < length; i++) {answer[i] = nums[i - 1] * answer[i - 1];}// R 为右侧所有元素的乘积// 刚开始右边没有元素,所以 R = 1int R = 1;for (int i = length - 1; i >= 0; i--) {// 对于索引 i,左边的乘积为 answer[i],右边的乘积为 Ranswer[i] = answer[i] * R;// R 需要包含右边所有的乘积,所以计算下一个结果时需要将当前值乘到 R 上R *= nums[i];}return answer;}
}

更新于:

在这里插入图片描述

本篇blog会持续更新哦~

相关文章:

LeetCode-刷题记录-前缀和合集(本篇blog会持续更新哦~)

一、前缀和&#xff08;Prefix Sum&#xff09;算法概述 前缀和算法通过预先计算数组的累加和&#xff0c;可以在常数时间内回答多个区间和相关的查询问题&#xff0c;是解决子数组和问题中的重要工具。 它的基本思想是通过预先计算和存储数组的前缀和&#xff0c;可以在 O(1)…...

【中项第三版】系统集成项目管理工程师 | 第 4 章 信息系统架构③ | 4.6

前言 第4章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术相关的内容&#xff0c;学习要以教材为准。本章分值预计在4-5分。 目录 4.6 网络架构 4.6.1 基本原则 4.6.2 局域网架构 4.6.3 广域网架构 4.6.4 移动通信网架构 4.6.5 软件定义网络 4.6…...

知识图谱入门笔记

自学参考&#xff1a; 视频&#xff1a;斯坦福CS520 | 知识图谱 最全知识图谱综述 详解知识图谱的构建全流程 知识图谱构建&#xff08;概念&#xff0c;工具&#xff0c;实例调研&#xff09; 一、基本概念 知识图谱&#xff08;Knowledge graph&#xff09;&#xff1a;由结…...

常见的气体流量计有哪些?

1.气体涡轮流量计 适用场合&#xff1a;流量变化小&#xff0c;脉动流频率小&#xff0c;中低压洁净天然气优点 1.精度高&#xff0c;重复性好 2.测量范围广&#xff0c;压损小&#xff0c;安装维修方便 3.具有较高的抗电磁干扰和抗震动能力缺点&#xff1a;分辨率低&#xff…...

AI推介-大语言模型LLMs论文速览(arXiv方向):2024.07.01-2024.07.05

文章目录&#xff5e; 1.LLM Internal States Reveal Hallucination Risk Faced With a Query2.Fine-Tuning with Divergent Chains of Thought Boosts Reasoning Through Self-Correction in Language Models3.Investigating Decoder-only Large Language Models for Speech-t…...

Android IP地址、子网掩码、默认网关、首选DNS服务器、备用DNS服务器校验

Android IP地址、子网掩码、默认网关、首选DNS服务器、备用DNS服务器校验 public String isIP(String ip) {String regex = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)){3}";Pattern p = Pattern.compile(regex)...

铁威马NAS教程丨为什么修复文件系统、为卷扩容、增加及删除 SSD 缓存等操作失败?

适用机型&#xff1a; 所有 TNAS 型号 适用版本&#xff1a; 所有 TOS 版本 问题现象&#xff1a; 在尝试修复文件系统、为卷扩容、增加或删除 SSD 缓存时(TOS 5)&#xff0c;可能因卷被其他进程占用而操作失败。 解决方法&#xff1a; 为了成功执行上述操作&#xff0c;您…...

【深度学习】第3章——回归模型与求解分析

一、回归分析 1.定义 分析自变量与因变量之间定量的因果关系&#xff0c;根据已有的数据拟合出变量之间的关系。 2.回归和分类的区别和联系 3.线性模型 4.非线性模型 5.线性回归※ 面对回归问题&#xff0c;通常分三步解决 第一步&#xff1a;选定使用的model&#xff0c;…...

Maven的基本使用

引入依赖 1.引入Maven仓库存在的依赖&#xff0c;直接引入&#xff0c;刷新Maven <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.12.RELEASE</version> </dependency…...

【笔记】finalshell中使用nano编辑器GNU

ctrl O 保存 enter 确定 ctrl X 退出 nano编辑 能不用就不用吧 因为我真用不习惯 nano编辑的文件也可以用vim编辑的...

markdown文件转pdf

步骤&#xff1a;md转html转pdf pom引入 <!--markdown 转pdf--><dependency><groupId>com.vladsch.flexmark</groupId><artifactId>flexmark-all</artifactId><version>0.64.8</version></dependency><dependency&g…...

课设:二手车交易管理系统(Java+MySQL)

简易数据库课程设计~分享 技术栈 本项目使用以下技术栈构建&#xff1a; Java: 作为主要编程语言&#xff0c;负责业务逻辑的实现。MySQL: 用于数据存储&#xff0c;管理用户、车辆和订单信息。JDBC: 用于Java与MySQL数据库之间的连接和操作。Swing GUI: 提供用户图形界面&am…...

vue3实现无缝滚动 列表滚动 vue3-seamlessscroll

vue3框架内使用无缝滚动&#xff0c;使用一个插件比较合适&#xff08;gitee地址&#xff09;&#xff1a; vue3-seamless-scroll: Vue3.0 无缝滚动组件 具体更多配置请看&#xff1a; 组件配置 | vue3-scroll-seamless 1. 安装&#xff1a; npm install vue3-seamless-sc…...

Python酷库之旅-第三方库Pandas(012)

目录 一、用法精讲 28、pandas.HDFStore.keys函数 28-1、语法 28-2、参数 28-3、功能 28-4、返回值 28-5、说明 28-6、用法 28-6-1、数据准备 28-6-2、代码示例 28-6-3、结果输出 29、pandas.HDFStore.groups函数 29-1、语法 29-2、参数 29-3、功能 29-4、返回…...

SpringCloud集成nacos之jasypt配置中心的密码加密的自动解密

目录 1.引入相关的依赖 2.nacos的yaml的相关配置&#xff0c;配置密码和相关算法 3.配置数据源连接 3.1 数据库连接配置 4.连接数据库配置类详解&#xff08;DataSourceConfig&#xff09;。 5.完整的配置类代码如下 1.引入相关的依赖 <dependency><groupId>…...

Python 中将字典内容保存到 Excel 文件使用详解

概要 在数据处理和分析的过程中,经常需要将字典等数据结构保存到Excel文件中,以便于数据的存储、共享和进一步分析。Python提供了丰富的库来实现这一功能,其中最常用的是pandas和openpyxl。本文将详细介绍如何使用这些库将字典内容保存到Excel文件中,并包含具体的示例代码…...

libaom 编码器 aomenc 使用文档介绍

使用方法&#xff1a;./aomenc <选项> -o 目标文件名 源文件名 使用 --help 查看完整的选项列表。 选项&#xff1a; --help 显示使用选项并退出-c <参数>, --cfg<参数> 使用配置文件-D, --debug 调试模式&#xff08;使输出确定性&#xff09;-o <参数&g…...

速盾:cdn 缓存图片

现如今&#xff0c;互联网已经成为我们日常生活中不可或缺的一部分。在我们使用互联网时&#xff0c;经常会遇到图片加载缓慢、文章打开慢等问题。为了解决这些问题&#xff0c;CDN&#xff08;内容分发网络&#xff09;应运而生。CDN 是一种通过将数据缓存在世界各地的服务器上…...

移动应用开发课设——原神小助手文档(2)

2023年末&#xff0c;做的移动应用开发课设&#xff0c;分还算高&#xff0c;项目地址&#xff1a;有帮助的话&#xff0c;点个赞和星呗~ GitHub - blhqwjs/-GenShin_imp: 2023年移动应用开发课设 本文按照毕业论文要求来写&#xff0c;希望对大家有所帮助。 接上文&#xff1a…...

智能聊天机器人:使用PyTorch构建多轮对话系统

使用PyTorch构建多轮对话系统的示例代码。这个示例项目包括一个简单的Seq2Seq模型用于对话生成&#xff0c;并使用GRU作为RNN的变体。以下是代码的主要部分&#xff0c;包括数据预处理、模型定义和训练循环。 数据预处理 首先&#xff0c;准备数据并进行预处理。这部分代码假…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

理想汽车5月交付40856辆,同比增长16.7%

6月1日&#xff0c;理想汽车官方宣布&#xff0c;5月交付新车40856辆&#xff0c;同比增长16.7%。截至2025年5月31日&#xff0c;理想汽车历史累计交付量为1301531辆。 官方表示&#xff0c;理想L系列智能焕新版在5月正式发布&#xff0c;全系产品力有显著的提升&#xff0c;每…...

数据库优化实战指南:提升性能的黄金法则

在现代软件系统中&#xff0c;数据库性能直接影响应用的响应速度和用户体验。面对数据量激增、访问压力增大&#xff0c;数据库性能瓶颈经常成为项目痛点。如何科学有效地优化数据库&#xff0c;提升查询效率和系统稳定性&#xff0c;是每位开发与运维人员必备的技能。 本文结…...

年度峰会上,抖音依靠人工智能和搜索功能吸引广告主

上周早些时候举行的第五届年度TikTok World产品峰会上&#xff0c;TikTok推出了一系列旨在增强该应用对广告主吸引力的功能。 新产品列表的首位是TikTok Market Scope&#xff0c;这是一个全新的分析平台&#xff0c;为广告主提供整个考虑漏斗的全面视图&#xff0c;使他们能够…...

Java严格模式withResolverStyle解析日期错误及解决方案

在Java中使用DateTimeFormatter并启用严格模式&#xff08;ResolverStyle.STRICT&#xff09;时&#xff0c;解析日期字符串"2025-06-01"报错的根本原因是&#xff1a;模式字符串中的年份格式yyyy被解释为YearOfEra&#xff08;纪元年份&#xff09;&#xff0c;而非…...

LSTM-XGBoost多变量时序预测(Matlab完整源码和数据)

LSTM-XGBoost多变量时序预测&#xff08;Matlab完整源码和数据&#xff09; 目录 LSTM-XGBoost多变量时序预测&#xff08;Matlab完整源码和数据&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 普通的多变量时序已经用腻了&#xff0c;审稿人也看烦了&#…...

2025年ESWA SCI1区TOP,自适应学习粒子群算法AEPSO+动态周期调节灰色模型,深度解析+性能实测

目录 1.摘要2.粒子群算法PSO原理3.改进策略4.结果展示5.参考文献6.代码获取7.算法辅导应用定制读者交流 1.摘要 能源数据的科学预测对于能源行业决策和国家经济发展具有重要意义&#xff0c;尤其是短期能源预测&#xff0c;其精度直接影响经济运行效率。为了更好地提高预测模型…...