【优先算法】思还故里闾,欲归道无因 - 前缀和

在这里插入图片描述

本篇博客给大家带来的是前缀和算法的知识点, 也是一样通过OJ题理解,掌握,应用该算法.
🐎文章专栏: 算法
🚀若有问题 评论区见
欢迎大家点赞 评论 收藏 分享
如果你不知道分享给谁,那就分享给薯条.
你们的支持是我不断创作的动力 .

王子,公主请阅🚀

  • 要开心
    • 要快乐
      • 顺便进步
    • 1. 和为K的子数组
    • 2. 和可被 K 整除的⼦数组(蓝桥杯真题)
    • 3. 连续数组
    • 4. 矩阵区域和

要开心

要快乐

顺便进步

1. 和为K的子数组

题目链接: 560. 和为 K 的子数组

题目描述:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2
示例 2:

输入:nums = [1,2,3], k = 3
输出:2

解法一: 暴力解法

在这里插入图片描述

定义计数变量count, 两层循环遍历数组, 每次 j 从 i 的位置开始,
找到满足 [ i , j ] 区间元素和等于k时,count++. 时间复杂度为O(N^2)

解法二: 前缀和 + 哈希表

1. 问题转换并分析

在这里插入图片描述

①是 以 i 位置为结尾的子数组,且①满足数组元素为 k.
由此图便可将问题转化为: 当遍历数组到 i 位置时, [ 0 , i-1 ]区间中前缀和为sum[i] - k的个数.

这个时候不要直接去求前缀和数组, 然后遍历找满足条件的前缀和. 如果这么做那时间复杂度还是O(N^2)并且空间复杂度还是O(N), 并不见得比暴力解法要好.
要找前缀和并且其满足sum[i] - k, 可以利用哈希表来找, 哈希表本身就是用来查找的. 哈希表: <前缀和,出现次数>

2. 算法思路

在这里插入图片描述

设 i 为数组中的任意位置,用 sum[i] 表示 [0, i] 区间内所有元素的和。
想知道有多少个「以 i 为结尾的和为 k 的子数组」,就要找到有多少个起始位置为 x1, x2,
x3… 使得 [x, i] 区间内的所有元素的和为 k 。那么 [0, x] 区间内的和是不是就是
sum[i] - k 了。于是问题就变成:
◦ 找到在 [0, i - 1] 区间内,有多少前缀和等于 sum[i] - k 的即可。

3. 处理细节

1. 我们不用真的初始化一个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于sum[i] - k 。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每⼀种前缀和出现的次数。 不要把前缀和都求出来后再加入哈希表, 原本应该是[ 0 , i-1 ] 的前缀和,但求完一并加入 会 使 [ i , n-1] 的前缀和也加进来, 假设[ i , n-1 ] 也有满足条件的前缀和, 就会多算.

2. 如果整个数组和为 k , 那么此时并不存在一个区间让我去找 前缀和 = sum[i] - k, 但是sum[i] = k 这个情况确实存在, 所以在我开始遍历数组之前, 应该先map.put(0,1), sum[i] - k = 0时, 次数赋为1.

在这里插入图片描述

4. 代码实现

class Solution {public int subarraySum(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<>();//将前缀和为0的初始次数设置为1, 因为 k 有可能等于nums数组中某个元素的值.map.put(0,1);int sum = 0,ret = 0;for(int x : nums) {sum += x;//计算当前位置的前缀和.ret += map.getOrDefault(sum-k,0);//统计结果.map.put(sum,map.getOrDefault(sum,0)+1);//将当前位置的前缀和sum加入哈希表.}return ret;}
}

2. 和可被 K 整除的⼦数组(蓝桥杯真题)

题目链接: 974. 和可被 K 整除的⼦数组

题目描述:

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的非空 子数组 的数目。

子数组 是数组中 连续 的部分。

示例 1:

输入:nums = [4,5,0,-2,-3,1], k = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 k = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:

输入: nums = [5], k = 9
输出: 0

解法一: 暴力枚举

做法与上题基本一致, 就是枚举出所有子数组的和, 时间复杂度为O(N^2).

解法二: 前缀和 + 哈希表

第一点 必要前置知识:

1. 同余定理
如果(a - b) % p = 0 , 那么 a % p = b % p . 即 如果两个数相减的差能被 p 整除,那么这两个数对 p 取模的结果相同. 例如: (7 - 4) % 3 = 0, 7 % 3 = 1, 4 % 3 = 1;

在这里插入图片描述根据同余定理就可以把问题转换成, 在[0 , i-1]区间中找到满足 前缀和 % k 等于 sum[i] % k 的 所有前缀和. (这也是本题的核心.)

2. 负数取模

C++和Java中, 负数 % 正数 结果为 负数, 为了防止 重复算,统一将结果化为正数. 比如 -1 % 3 = -1 换成 (-1 % 3 + 3) % 3 = 2 . 即 a % p -> (a % p + p) % p .

第二: 具体步骤(与上题无异, 不同的是,此题中map第一个位置放的时前缀和 % k 的值. 并且确保是正数.)
在这里插入图片描述

设 i 为数组中的任意位置,⽤ sum[i] 表示 [0, i] 区间内所有元素的和。
• 想知道有多少个「以 i 为结尾的可被 k 整除的子数组」,就要找到有多少个起始位置为 x1, x2, x3… 使得 [x, i] 区间内的所有元素的和可被 k 整除。
• 设 [0, x ] (x < i)区间内所有元素之和等于 a , [0, i] 区间内所有元素的和等于 b ,可得
(b - a) % k == 0 。
• 由同余定理可得, [0, x ] 区间与 [0, i] 区间内的前缀和同余。于是问题就变成:
◦ 找到在 [0, i - 1] 区间内,有多少前缀和的余数等于 sum[i] % k 的即可。
我们不用真的初始化⼀个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于sum[i] - k 。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每⼀种前缀和出现的次数。

第三 代码实现

class Solution {public int subarraysDivByK(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<Integer,Integer>();map.put(0,1);//还是一样的,[0,i] 当sum = k时,不存在区间,但sum[i] = k存在.int sum = 0,ret = 0;for(int x : nums) {sum += x;//当前位置的前缀和int tmp = (sum % k + k) % k;//前缀和模k 的余数,原本是sum % k, 但是Java和C++存在负数模正数等于负数的问题,一并化成正数.ret += map.getOrDefault(tmp,0);map.put(tmp,map.getOrDefault(tmp,0)+1);}return ret;}
}

3. 连续数组

题目链接: 525. 连续数组

题目描述:

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。

示例 1:

输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:

输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

1. 暴力枚举

枚举出所有子数组, 检查子数组是否满足要求,时间复杂度为O(N^2).

2. 前缀和 + 哈希表

第一 问题分析与转换
原数组中的元素只有0和1, 题目要求的是 0 和 1 个数相等的最长子数组, 将所有的 0 换成 -1, 问题就转换成 求 和为0的最长子数组的长度.

在这里插入图片描述

第二 处理细节

1. 哈希表<In,In>的两个位置分别存放 [ 0 , i ]前缀和 与 位置 i .

在这里插入图片描述

2. 当区间[ 0 , i ]的sum[i] = 0时, 0 < j < i,不存在[0 , j] 区间. 默认一个前缀和为0的情况, 只能以 -1 为结束位置.

3. 如果有重复的sum[ i ] , 保留前面先算出来的 <sum ,i>, 舍弃后面的, 因为先算出来的更靠左边, 离 i 的距离更大, 本题要求的就是最大长度.

在这里插入图片描述

第三 步骤

在这里插入图片描述

设 i 为数组中的任意位置,⽤ sum[i] 表⽰ [0, i] 区间内所有元素的和。
想知道最⼤的「以 i 为结尾的和为 0 的⼦数组」,就要找到从左往右第⼀个 x1 使得
[x1, i]区间内的所有元素的和为 0 。那么 [0, x1 - 1] 区间内的和是不是就是 sum[i] 了。于是问题
就变成:
• 找到在 [0, i - 1] 区间内,第⼀次出现 sum[i] 的位置即可。
我们不⽤真的初始化⼀个前缀和数组,因为我们只关⼼在 i 位置之前,第⼀个前缀和等于 sum[i]的位置。因此,我们仅需⽤⼀个哈希表,⼀边求当前位置的前缀和,⼀边记录第⼀次出现该前缀和的
位置。

第四 代码实现

class Solution {public int findMaxLength(int[] nums) {Map<Integer,Integer> hash = new HashMap<>();hash.put(0,-1); //当[0,i]sum = 0时,默认存在一个前缀和为0的情况.并且以-1为结束位置.int sum = 0,ret = 0;for(int i = 0;i < nums.length;++i) {if(nums[i] == 0) {sum += -1; //将数组中所有的 0 替换成 -1.}else {sum += nums[i];//求出当前位置的前缀和}if(hash.containsKey(sum-0)) {ret = Math.max(ret,i - hash.get(sum));}else{//有重复的只保留前面的那一对<sum,i>.  hash.put(sum,i);}}return ret;}
}

4. 矩阵区域和

题目链接: 1314. 矩阵区域和

题目描述:

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

i - k <= r <= i + k,
j - k <= c <= j + k 且
(r, c) 在矩阵内。

示例 1:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[12,21,16],[27,45,33],[24,39,28]]
示例 2:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2
输出:[[45,45,45],[45,45,45],[45,45,45]]

提示:

m == mat.length
n == mat[i].length
1 <= m, n, k <= 100
1 <= mat[i][j] <= 100

本篇博客到这里就结束啦, 感谢观看 ❤❤❤

🐎期待与你的下一次相遇😊😊😊

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

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

相关文章

亿道三防丨三防笔记本是什么意思?和普通笔记本的优势在哪里?

三防笔记本是什么意思&#xff1f;和普通笔记本的优势在哪里&#xff1f; 在现代社会中&#xff0c;笔记本电脑已经成为人们工作和生活中不可或缺的一部分。然而&#xff0c;在一些特殊行业或环境中&#xff0c;普通笔记本电脑由于其脆弱性和对环境条件的敏感性&#xff0c;往…

SOME/IP 协议详解——服务发现

文章目录 1. Introduction &#xff08;引言&#xff09;2. SOME/IP Service Discovery (SOME/IP-SD)2.1 General&#xff08;概述)2.2 SOME/IP-SD Message Format2.2.1 通用要求2.2.2 SOME/IP-SD Header2.2.3 Entry Format2.2.4 Options Format2.2.4.1 配置选项&#xff08;Co…

Go语言之路————go环境的初始化

Go语言之路————go环境的初始化 前言一、Go的安装二、环境配置三、初始化一个新项目四、常用的一些指令 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#xff0c;到后面能正…

鸿蒙UI开发——基于onTouch事件实现表情选择胶囊

1、背 景 有朋友留言说&#xff0c;抖音APP中&#xff0c;长按评论按钮触发的快捷表情选择胶囊动画比较好&#xff08;效果如下图&#xff09;&#xff0c;希望使用鸿蒙ArkTs也实现一个类似的。 本文在鸿蒙ArkTs下也实现一个类似的效果&#xff0c;如下&#xff1a; 首先&…

Node.js——http 模块(二)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

研华 PCI-1751 驱动更新导LabVIEW致程序异常

问题描述&#xff1a; 某 LabVIEW 程序长期运行正常&#xff0c;但在使用研华 PCI-1751 数据采集卡运行一段时间后&#xff0c;程序开始出现不正常的行为。具体过程如下&#xff1a; 初始问题&#xff1a; 更换新的 PCI-1751 板卡后&#xff0c;驱动程序被更新&#xff0c;但程…

接上篇基于Alertmanager 配置钉钉告警

Alertmanager 是一个用于处理和管理 Prometheus 警报的开源工具。它负责接收来自 Prometheus 服务器的警报&#xff0c;进行去重、分组、静默、抑制等操作&#xff0c;并通过电子邮件、PagerDuty、Slack 等多种渠道发送通知。 主要功能 去重&#xff1a;合并相同或相似的警报&…

网络原理(三)—— 传输层 之 UDP 和 TCP协议

传输层 在传输层两大关键的协议就是UDP和TCP协议了&#xff0c;除此之外&#xff0c;还有别的传输层协议&#xff0c;本文章将介绍UDP和TCP协议&#xff0c;重点介绍TCP协议。 首先回顾TCP和UDP 的特点&#xff1a; UDP&#xff1a;不可靠传输&#xff0c;面向数据包&#xf…

针对服务器磁盘爆满,MySql数据库始终无法启动,怎么解决

&#xff08;点击即可进入聊天助手&#xff09; 很多站长在运营网站的过程当中都会遇到一个问题,就是网站突然无法打开,数据一直无法启动 无论是强制重启还是,删除网站内的所有应用,数据库一直无法启动 这个时候,就需要常见的运维手段了,需要对服务器后台各个资源,进行逐一排查…

高性能现代PHP全栈框架 Spiral

概述 Spiral Framework 诞生于现实世界的软件开发项目是一个现代 PHP 框架&#xff0c;旨在为更快、更清洁、更卓越的软件开发提供动力。 特性 高性能 由于其设计以及复杂精密的应用服务器&#xff0c;Spiral Framework框架在不影响代码质量以及与常用库的兼容性的情况下&a…

【STM32-学习笔记-6-】DMA

文章目录 DMAⅠ、DMA框图Ⅱ、DMA基本结构Ⅲ、不同外设的DMA请求Ⅳ、DMA函数Ⅴ、DMA_InitTypeDef结构体参数①、DMA_PeripheralBaseAddr②、DMA_PeripheralDataSize③、DMA_PeripheralInc④、DMA_MemoryBaseAddr⑤、DMA_MemoryDataSize⑥、DMA_MemoryInc⑦、DMA_DIR⑧、DMA_Buff…

SQL Server中可以通过扩展事件来自动抓取阻塞

在SQL Server中可以通过扩展事件来自动抓取阻塞&#xff0c;以下是详细流程&#xff1a; 开启阻塞跟踪配置&#xff1a; • 执行以下SQL语句来启用相关配置&#xff1a; EXEC sp_configureshow advanced options, 1; RECONFIGURE; EXEC sp_configure blocked process thresh…

【爬虫】单个网站链接爬取文献数据:标题、摘要、作者等信息

源码链接&#xff1a; https://github.com/Niceeggplant/Single—Site-Crawler.git 一、项目概述 从指定网页中提取文章关键信息的工具。通过输入文章的 URL&#xff0c;程序将自动抓取网页内容 二、技术选型与原理 requests 库&#xff1a;这是 Python 中用于发送 HTTP 请求…

关于扫描模型 拓扑 和 传递贴图工作流笔记

关于MAYA拓扑和传递贴图的操作笔记 一、拓扑低模: 1、拓扑工作区位置: 1、准备出 目标 高模。 (高模的状态如上 ↑ )。 2、打开顶点吸附,和建模工具区,选择四边形绘制. 2、拓扑快捷键使…

解决无法远程管理Windows Server服务器核心安装

问题 有时&#xff0c;人们会为了节省运算资源&#xff0c;例如运行Hyper-V虚拟机&#xff0c;而选择Windows Server核心安装&#xff0c;即无图形化界面。这时&#xff0c;我们就只能通过Powershell命令对其进行操控&#xff0c;或为了获得图形化界面而使用远程服务器管理工具…

【计算机网络】lab7 TCP协议

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;计算机网络_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 实验目的…

JavaRestClient 客户端初始化+索引库操作

1. 介绍 ES官方提供了各种不同语言的客户端&#xff0c;用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过http请求发送给ES。 Elasticsearch目前最新版本是8.0&#xff0c;其java客户端有很大变化。不过大多数企业使用的还是8以下版本 2. 客户端初始化 在elastic…

【JVM-2.2】使用JConsole监控和管理Java应用程序:从入门到精通

在Java应用程序的开发和运维过程中&#xff0c;监控和管理应用程序的性能和资源使用情况是非常重要的。JConsole是Java Development Kit&#xff08;JDK&#xff09;自带的一款图形化监控工具&#xff0c;它可以帮助开发者实时监控Java应用程序的内存、线程、类加载以及垃圾回收…

基于html5实现音乐录音播放动画源码

源码介绍 基于html5实现音乐录音播放动画源码是一款类似Shazam的UI&#xff0c;点击按钮后&#xff0c;会变成为一个监听按钮。旁边会有音符飞入这个监听按钮&#xff0c;最后转换成一个音乐播放器。 效果预览 源码获取 基于html5实现音乐录音播放动画源码

《自动驾驶与机器人中的SLAM技术》ch1:自动驾驶

目录 1.1 自动驾驶技术 1.2 自动驾驶中的定位与地图 1.1 自动驾驶技术 1.2 自动驾驶中的定位与地图 L2 在技术实现上会更倾向于实时感知&#xff0c;乃至可以使用感知结果直接构建鸟瞰图&#xff08;bird eye view, BEV&#xff09;&#xff0c;而 L4 则依赖离线地图。 高精地…