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

前缀和(和可被K整除的子数组)(6)

https://blog.csdn.net/2601_95366422/article/details/158841676

上节课链接

一.题目

974. 和可被 K 整除的子数组 - 力扣(LeetCode)

二.思路

2.1 错误思路

这题同样不可以使用滑动窗口,和上一题和为k的子数组一样的问题!

2.2 重要知识讲解

同余定理:如果两个数ab的差能被k整除,那么它们对k取余的结果相等,即

(a−b)%k==0 ⟺ a%k == b%k

修正求余:在C++中,负数对正数取余的结果是负数(例如-1 % 5 = -1),这与数学上的余数定义不同。因此需要修正,修正公式为:

mod = (sum % k + k) % k

2.3 正确思路

我们采用前缀和 + 哈希表的方法。定义前缀和sum为从数组起始到当前位置的累加和。根据同余定理,子数组[j+1, i]的和能被k整除等价于sum[i] % k == sum[j] % k。因此,我们只需要统计有多少对前缀和的余数相等。

遍历数组,计算当前前缀和sum,并用修正公式得到当前余数mod。然后,在哈希表中查找之前出现过多少次相同的mod,这些次数就是能与当前位置构成合法子数组的个数,累加到答案中。最后将当前mod的出现次数加一,供后续使用。

三.代码演示

class Solution { public: int subarraysDivByK(vector<int>& nums, int k) { unordered_map<int,int>hash; int sum = 0; int ret = 0; hash[0] = 1; for(const auto& x:nums) { sum += x; int r = (sum % k + k)%k;//求余数,这是修正的余数 if(hash.count(r)) ret += hash[r]; hash[r]++; } return ret; } };

四.代码讲解

一、初始化哈希表与变量

首先,我们需要一个哈希表(unordered_map<int, int>)来记录前缀和对 k 取余的结果出现的次数。在遍历数组之前,我们预先在哈希表中存入hash[0] = 1,这表示余数为 0 已经出现过一次(对应空数组的前缀和)。这个初始化至关重要,因为它能正确处理那些从数组开头开始且和能被 k 整除的子数组。同时,定义两个变量:sum用于累加当前的前缀和,初始为 0;ret用于统计满足条件的子数组个数,初始为 0。

二、遍历数组并更新前缀和与余数

使用范围for循环遍历数组中的每一个元素x。对于每个元素,执行以下操作:

  1. 更新当前前缀和sum += x。此时sum表示从数组起始位置到当前元素(包含当前元素)的累加和。

  2. 计算修正后的余数:由于 C++ 中负数取余的结果为负数,为了统一比较,我们需要将余数修正为非负数。计算公式为:r = (sum % k + k) % k。这个r就是当前前缀和对 k 取余的标准结果,范围在[0, k-1]

  3. 检查之前是否存在相同余数:在哈希表中查找键r。根据同余定理,如果之前出现过余数也为r的前缀和,那么从那个位置的下一个元素到当前位置形成的子数组的和一定能被 k 整除。因此,如果哈希表中存在r,则将其对应的出现次数累加到结果ret中。注意,这里累加的是次数,因为可能有多个不同的起始位置都能与当前结束位置构成合法子数组。

  4. 记录当前余数:将当前余数r在哈希表中的计数加 1,以便后续元素使用。这保证了之后遇到更大的下标时,可以查询到当前这个余数的出现次数。

三、关键细节
  • 哈希表的作用:以 O(1) 的时间快速查询之前出现过多少次特定的余数,将双层循环的 O(n²) 优化为 O(n)。

  • 初始化hash[0] = 1的原因:考虑子数组从下标 0 开始的情况,此时子数组的和就是当前前缀和sum,需要满足sum % k == 0,即余数为 0。因此我们需要在哈希表中提前存好余数 0 的出现次数为 1,这样才能正确统计这类子数组。

  • 修正余数的必要性:因为数组元素可能为负,直接使用sum % k可能得到负数,而负数无法正确映射到哈希表的索引(且与数学意义上的余数不一致)。通过(sum % k + k) % k,我们确保余数始终非负,从而能正确比较。

  • 同余定理的应用:核心在于将“和能被 k 整除”转化为“两个前缀和的余数相等”,从而将问题转化为统计相同余数出现的对数。

http://www.jsqmd.com/news/538834/

相关文章:

  • 如何一键安全弹出USB设备:Windows用户的终极解决方案
  • 免费的往往最贵?2026年高性价比网盘深度测评与避坑指南(含5款主流工具实测)
  • 闲置华润万家卡别浪费,帮你高效回收变现 - 猎卡回收公众号
  • 美团周末五折,亲测解答:鱼你在一起的招牌巴沙鱼加米饭外卖好吃吗? - 资讯焦点
  • 2026实测分享!靠谱省心的三种分期乐京东e卡套装回收平台 - 猎卡回收公众号
  • 基于策略模式与智能编排的抖音批量下载系统架构设计与实现
  • 预印本论文从哪里找?优缺点与使用建议
  • 从零开始:StaMPS地表形变监测软件快速部署与实战指南
  • 软件工程师如何转型AI工程师 第四章 工程化——被严重低估的护城河
  • 转:要“豁出性命”理解他人
  • 如何用91160-cli解决医院挂号难题:全自动医疗预约的完整解决方案
  • Zephyr开发环境搭建避坑指南:从Ubuntu配置到STM32烧录全流程
  • 北京记录者商行上门回收 于先生 18910232290 - 品牌排行榜单
  • 用74ls10和74ls20与非门搭建四人表决器:从真值表到电路图的完整设计流程
  • 2026 终极指南:5 款主流 Obsidian 同步方案深度测评,哪家最稳定?
  • 2272 上市公司绿色创新波动性(1994-2022)
  • 开源视频获取工具:从流媒体到本地存储的完整解决方案
  • 大模型落地指南:微调、成本与安全,一篇搞定!
  • 易语言飞将ddddocr识图识字PaddleOCR识图识字苍狼OCR简单识字简化
  • 给视觉新手的保姆级教程:用Python+OpenCV玩转四步相移结构光(附代码)
  • 144页顶流LLM全景综述爆了!人大团队整理1000+论文,把大模型前世今生讲透
  • 文科生被AI大厂疯抢,月薪3万起,这条热搜,你真的看懂了吗?
  • ## 31|OpenTelemetry 与 Python 全链路可观测:指标、日志、追踪三位一体
  • Deepin系统防火墙配置全攻略:从开放端口到安全防护(附UFW命令大全)
  • HunyuanVideo-FoleyGPU算力优化实践:24GB显存利用率提升30%实测分析
  • League-Toolkit:提升英雄联盟游戏效率的智能辅助解决方案
  • 探讨2026年岳阳无人机培训去哪里好,这些机构值得关注 - 工业推荐榜
  • OpenClaw人人养虾:网关架构
  • 停止“重复写Prompt“!用AI Agent Skill,让AI真正“会干活”!
  • 稀土抑烟剂:PVC燃烧中的“减烟卫士”