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

【数据结构与算法】同余计算 哈希表与前缀和问题特征和模板化思路

加减乘负的类同余计算

加乘模情况

  1. 两数和模 : (a + b) mod m = (a mod m + b mod m) mod m
  2. 乘积模 : (a * b) mod m = ((a mod m) * (b mod m)) mod m

加模证明如下 :

  1. a = q1 * m + r1 , b = q2 * m + r2
  2. a mod m = r1 , b mod m = r2
  3. (a + b) mod m = ((q1 + q2) * m + (r1 + r2)) mod m = (r1 + r2) mod m = (a mod m + b mod m) mod m

结论 : 两数和模或乘积模与其非模本部无关 .

减模零情况

减模零即 ( a - b ) mod m = 0 . 记作 a ≡ b ( mod m )

数学范围内的模数通常不小于 0 , Java 中取模 % 操作得到的模数的符号与被模数相同 , 负数取模有 : 首先取得负数绝对值的模数 , 模数的相反数即 Java 模数 . 因此要在需求场景将正负模数统一 , 公式如下 :

  • a ≡ b -> ( a mod m + m ) mod m = ( b mod m + m ) mod m

哈希表与前缀和结合

问题特征

哈希前缀和结合一般能够解决求满足特定条件的子数组的个数的问题 , 这类问题如果不涉及模计算 , 数据通常有负 , 无法使用滑动窗口算法解决 . sum[i] - sum[j] 表示 从下标 j + 1i 的共 i - j 个元素的总和 , 通常题目条件有 :

  1. 是否存在 / 获取最长子数组 : 523. 连续的子数组和 和 525. 连续数组 分别对应两种情况 .
  2. 满足条件的子数组个数 : 560. 和为 K 的子数组 模板题 .

前缀和补足了滑动窗口的数据局限性 , 将维护变量优化成寻找两个索引值满足条件 , 哈希表在其中起到了保存前索引的功能 .

套路

  1. 获取前缀和数组 .
    • 可以在接下来的遍历中获取前缀和 , 将 n 空间压缩成 1 空间 , 但由于前缀和数组和本数组的错位性 ( 通常 sum[0] 取 0 ) , 需要对初始化的哈希表进行预处理 .
  2. 推导题目要求的条件公式 .
  3. 分离条件公式中的前索引值和当前索引值到等式两端 .
  4. 在哈希表中寻找当前索引满足公式当前索引侧的个数 / 索引 .
  5. 将当前索引视为前索引记录满足等式另一侧的个数 / 索引 .
  6. 根据题目要求返回的数据不同维护不同变量 .
    1. 如是否存在 / 获取最长子数组问题 : 哈希表存值最早出现的位置索引 , 查最早出现位置后满足条件的位置 , 返回存在性 / 其中的最大值 .
    2. 满足条件的子数组个数问题 : 每次遍历使值满足条件的哈希值增加 , 维护值满足条件的子数组数量 , 查后续位置满足条件的个数 , 维护满足个数 .

就 560. 和为 K 的子数组 而言 , 根据套路步骤获得的条件公式 : sum[i] - sum[j] = k , 其中 sum[j] 为前索引值 , 移项得 sum[j] = k - sum[i] , 题目要求返回满足条件的子数组个数 , 所以存值等于 sum[i] - k 出现的次数 , 每次查询 sum[i] 在哈希表的映射值即可 .

看较复杂情况 2845. 统计趣味子数组的数目 题目的条件公式为 ( sum[i] - sum[j] ) % modulo = k , 经过变换得到 ( sum[i] - k ) % modulo = sum[j] % modulo , 所以要存 sum[i] % modulo , 查 ( sum[i] - k ) % modulo .

此外 , 如果题目要求返回子数组中特定值元素个数等于给定值的子数组个数 , 如 1248. 统计「优美子数组」 统计子数组中恰好有 k 个奇数数字的子数组个数时 , 可以先将对数组进行预处理 ( 如取奇数元素等于 1 , 其他等于 0 ) 后再推演套路 .

相关文章:

  • 滚珠螺杆的精度如何保持?
  • Nacos源码—3.Nacos集群高可用分析二
  • Vue中的过滤器参数:灵活处理文本格式化
  • Docker 使用下 (二)
  • 知识图谱 + 大语言模型:打造更聪明、更可靠的AI大脑 —— 探索 GraphRAG 中文优化与可视化实践
  • VirtualBox调整虚拟机内存和CPU
  • 数据库的原子事务
  • 阿里云物联网平台--云产品流传
  • Qt6.8中进行PDF文件读取和编辑
  • 【Java学习笔记】包
  • LeetCode 0790.多米诺和托米诺平铺:难想条件的简单动态规划
  • 实验-数字电路设计2-复用器和七段数码管(数字逻辑)
  • 设计模式每日硬核训练 Day 18:备忘录模式(Memento Pattern)完整讲解与实战应用
  • Python基本语法(类和实例)
  • 基于MATLAB的图像色彩识别项目,彩色图像矩阵识别
  • Java:从入门到精通,你的编程之旅
  • 预训练到微调:深入理解AI的上下游任务
  • 访问计划(C++)
  • 【SpringBoot篇】详解短信验证码登录功能实现
  • 学习黑客Nmap 命令法诀
  • 从陈毅杯到小应氏杯,五一长假上海掀起围棋热
  • 云南禄丰一尾矿干堆场坍塌致5人被埋
  • 塞尔维亚总统因突发健康问题,中断对美国的正式访问并回国
  • 经济日报:仅退款应平衡各方权益
  • 在“蟑螂屋”里叠衣服,我看见人生百态
  • 视频公开课上线之后,北大成为多少人未曾谋面的母校?