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

news2024/11/17 15:36:23

一、前缀和(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; // 初始前缀和为0
        int 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 的子数组和为 goal
            ans += 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; // 初始化前缀和为0
        int ans = 0; // 初始化结果为0
        map.put(sum,1); // 将初始的前缀和0放入哈希表,并设其出现次数为1
        // 遍历数组
        for(int num : nums){
            sum += num; // 计算当前位置的前缀和
            // 如果哈希表中存在前缀和为sum-k的项,则说明存在和为k的子数组 sum - (sum-k) = k
            if(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
    }
}


更新于:

在这里插入图片描述

本篇blog会持续更新哦~

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

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

相关文章

NCCL 中的一些辅助debug 知识点

1&#xff0c;调试nccl 启动kernel的方法 ncclLaunchKernel cuLaunchKernelEx ncclStrongStreamLaunchKernel cudaLaunchKernel ncclLaunchOneRank cudaLaunchKernel 在 nccl lib 中&#xff0c;不存在使用<<<grid, block,,>>> 这种类似方式启…

【咨询】企业数字档案馆(室)建设方案-模版范例

导读&#xff1a;本模版来源某国有大型医药行业集团企业数字档案馆&#xff08;室&#xff09;建设方案&#xff08;一期300W、二期250W&#xff09;&#xff0c;本人作为方案的主要参与者&#xff0c;总结其中要点给大家参考。 目录 1、一级提纲总览 2、项目概述 3、总体规…

【零基础】学JS之APIS(基于黑马)

喝下这碗鸡汤 披盔戴甲,一路勇往直前! 1. 什么是事件 事件是在编程时系统内发生的动作或者发生的事情 比如用户在网页上单击一个按钮 2. 什么是事件监听? 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应&#xff0c;也称为 注…

深度学习(笔记内容)

1.国内镜像网站 pip使用清华源镜像源 pip install <库> -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip使用豆瓣的镜像源 pip install <库> -i https://pypi.douban.com/simple/ pip使用中国科技大学的镜像源 pip install <库> -i https://pypi.mirro…

华为eNSP:HCIA汇总实验

本次拓扑实验需求&#xff1a; 1、内网地址用DHCP 2、VLAN10不能访问外网 3、使用静态NAT 实验用到的技术有DHCP、划分VLAN、IP配置、VLAN间的通信&#xff1a;单臂路由、VLANIF&#xff0c;静态NAT、基本ACL DHCP是一种用于自动分配IP地址和其他网络参数的协议。 划分VLA…

Elasticsearch:Node.js ECS 日志记录 - Winston

这是继上一篇文章 “Elasticsearch&#xff1a;Node.js ECS 日志记录 - Pino” 的续篇。我们继续上一篇文章来讲述使用 Winston 包来针对 Node.js 应用生成 ECS 向匹配的日子。此 Node.js 软件包为 winston 记录器提供了格式化程序&#xff0c;与 Elastic Common Schema (ECS) …

Linux系统下的用户管理模式

Linux系统下的用户管理模式 本文以属于Linux系统基本概念&#xff0c;如果以查找教程教程&#xff0c;解决问题为主&#xff0c;只需要查看本文后半部分。 如需要系统性学习请查看本文前半部分。 文章目录 Linux系统下的用户管理模式1. Linux下用户的概念2. 创建不同类型的用户…

前沿重器[53] | 聊聊搜索系统6:精排

前沿重器 栏目主要给大家分享各种大厂、顶会的论文和分享&#xff0c;从中抽取关键精华的部分和大家分享&#xff0c;和大家一起把握前沿技术。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。&#xff08;算起来&#xff0c;专项启动已经…

STM32实战篇:闪灯 × 流水灯 × 蜂鸣器

IO引脚初始化 即开展某项活动之前所做的准备工作&#xff0c;对于一个IO引脚来说&#xff0c;在使用它之前必须要做一些参数配置&#xff08;例如&#xff1a;选择工作模式、速率&#xff09;的工作&#xff08;即IO引脚的初始化&#xff09;。 IO引脚初始化流程 1、使能IO引…

TTS模型汇总

TTS是“Text-to-Speech”的缩写&#xff0c;中文意思是“文本到语音”。这是一种将文本信息转换成口语的技术&#xff0c;通常通过计算机程序实现。TTS技术可以应用于多种场景&#xff0c;包括但不限于&#xff1a; 辅助阅读&#xff1a;帮助视障人士或有阅读困难的用户通过听…

SHARPNESS-AWARE MINIMIZATION FOR EFFICIENTLY IMPROVING GENERALIZATION--论文笔记

论文笔记 资料 1.代码地址 https://github.com/google-research/sam https://github.com/davda54/sam 2.论文地址 https://arxiv.org/abs/2010.01412 3.数据集地址 论文摘要的翻译 在当今严重过度参数化的模型中&#xff0c;训练损失的值很难保证模型的泛化能力。事实上…

工业电脑一体机在高清视频处理中的应用

工业电脑一体机在高清视频处理中的应用广泛&#xff0c;尤其是在需要高性能计算、稳定性和实时处理能力的场景中。以下是工业电脑一体机在高清视频处理中的具体应用&#xff1a; 视频监控与分析&#xff1a; 工业电脑一体机能够处理多个高清视频流&#xff0c;实现实时监控&a…

echarts实现3D饼图

先看下最终效果 实现思路 使用echarts-gl的曲面图&#xff08;surface&#xff09;类型 通过parametric绘制曲面参数实现3D效果 代码实现 <template><div id"surfacePie"></div> </template> <script setup>import {onMounted} fro…

Kafka(三)Producer第二篇

一&#xff0c;生产者架构 生产者客户端由两个线程协调运行&#xff0c;分别为主线程和Sender线程&#xff08;发送线程&#xff09;。 主线程&#xff1a;KafkaProducer创建消息&#xff0c;通过拦截器、序列化器和分区器之后缓存到消息收集器RecordAccumulator中&#xff1b;…

Java面试八股之MySQL如何使用explain优化SQL和索引

MySQL如何使用explain优化SQL和索引 在MySQL中&#xff0c;EXPLAIN是一个非常有用的工具&#xff0c;用于分析和优化SQL查询。它可以帮助你理解查询执行计划&#xff0c;包括如何使用索引、表的连接方式、是否使用了临时表或文件排序等。以下是一些使用EXPLAIN来优化SQL查询和…

VBA经典应用69例应用5:使用VBA拆分窗格

《VBA经典应用69例》&#xff08;版权10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开&#xff0c;这套教程案例众多&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以便…

卷积神经网络可视化的探索

文章目录 训练LeNet模型下载FashionMNIST数据训练保存模型 卷积神经网络可视化加载模型一个测试图像不同层对图像处理的可视化第一个卷积层的处理第二个卷积层的处理 卷积神经网络是利用图像空间结构的一种深度学习网络架构&#xff0c;图像在经过卷积层、激活层、池化层、全连…

防火墙详解(USG6000V)

0、防火墙组网模式 防火墙能够工作在三种模式下分别是路由模式、透明模式、旁路检测模式、混合模式 0.1、路由模式 路由模式&#xff1a;防火墙全部以第三层对外连接&#xff0c;即接口具有IP 地址。一般都用在防火墙是边界的场景下 防火墙需要的部署/配置&#xff1a; 接…

自动连点鼠标器是什么?好用的鼠标连点器分享

你听说过自动鼠标连点器吗&#xff1f;自动连点鼠标器是一种软件工具&#xff0c;用于自动模拟鼠标点击操作。这种工具可以设置为在特定位置和时间间隔内自动点击鼠标&#xff0c;减轻手动点击的负担。自动连点器通常可以在很多生活场景中帮助我们节省时间成本&#xff0c;今天…

OS Copilot测评

1.按照第一步管理重置密码时报错了,搞不懂为啥?本来应该跳转到给的那个实例的,我的没跳过去 2.下一步重置密码的很丝滑没问题 3安全组新增入库22没问题 很方便清晰 4.AccessKey 还能进行预警提示 5.远程连接,网速还是很快,一点没卡,下载很棒 6.替换的时候我没有替换<>括…