首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

[算法]——前缀和(三)

  • 25-02-20 15:21
  • 4532
  • 9607
blog.csdn.net

目录

一、前言

二、正文

1.和为k的子数组

1.1  题目解析

1.2  算法原理

1.3  具体代码

2.和可被k整除的子数组

2.1  题目解析

2.2  算法原理

​编辑

2.3  具体代码

三、结语


一、前言

        本文将继续为小伙伴们带来前缀和的学习,希望大家能够从中有所收获呀!!!

二、正文

1.和为k的子数组

1. 和为 K 的子数组 - 力扣(LeetCode)

1.1  题目解析

        本题要求我们能够从所给整数数组中,统计所有子数组中所有元素和为k的次数

1.2  算法原理

        本题如果用暴力解法,就需要我们对数组中所有的子数组进行一一枚举并统计和是否k,时间复杂度为O(n²)。但是本题还有另一种解法,就是利用前缀和结合哈希表,乍一看可能小伙伴们觉得前缀和怎么和这道题能联系起来,其实需要我们对本题的求解进行一个转化。

        这个转化就是题目要求我们求一个子数组和为k,也就是当我们计算以i位置为结尾的的子数组合条件的时候,其实我们只需要看前面有多少个前缀和满足当前i位置的前缀和sum【i】-k,该次数就是所有以i位置为结尾的所有子数组的和,为了统计前缀和出现的次数,我们用一个哈希表来记录,时间复杂度为O(n)。

代码细节:

①前缀和插入哈希表的时候应该是在计算i位置之前,也就是在计算i位置之前,哈希表中只保存【0,i-1】位置的前缀和,而不是像之前一样我们先预处理玩所有的前缀和,再进行后续的处理,这是为了避免我们在计算以i位置结尾的子数组时,把i位置后面的前缀和也考虑进去

② 我们无需创建一个前缀和数组,因为在我们统计的时候我们只用到了i位置前一个位置的前缀合即sum[i-1],sum[i-1]+nums[i]即为sum[i],因此我们只需要用一个sum变量来标记前一个位置的前缀和即可

③当我们在求前缀和sum【i】-k的次数时,有可能遇到当前sum【i】=k的情况,这时候所需前缀和应为0,所以我们在统计的时候应该在哈希表中插入前缀和为0的情况,为了不遗漏sum【i】=k这一情况

1.3  具体代码

  1. class Solution {
  2. public:
  3. int subarraySum(vector<int>& nums, int k) {
  4. int sum=0,ret=0,n=nums.size();
  5. unordered_map<int,int> hash; //统计前缀和出现的次数
  6. hash[0]=1;
  7. for(int i=0;i<=n-1;i++)
  8. {
  9. sum+=nums[i];
  10. ret+=hash[sum-k];
  11. hash[sum]++;
  12. }
  13. return ret;
  14. }
  15. };

2.和可被k整除的子数组

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

2.1  题目解析

        本题与上题略有所不同,要我们从题目中所给数组中统计出来所有和可被K整除的子数组

2.2  算法原理

        对于本题,来说依旧存在暴力解法,即枚举所有子数组的和,并判断是否能被K整除,时间复杂度为O(n²),但是利用前缀和加哈希表我们就可以将时间复杂度降为O(n)。依旧是利用转换的思想,我们要求以i为结尾的子数组能够整除K,就是求【0,i-1】区间内能够多少个前缀和能够整除K,同样的,为了统计前缀和的次数我们用一个哈希表来记录。

代码细节:

①前缀和插入哈希表的时候应该是在计算i位置之前,也就是在计算i位置之前,哈希表中只保存【0,i-1】位置的前缀和,而不是像之前一样我们先预处理玩所有的前缀和,再进行后续的处理,这是为了避免我们在计算以i位置结尾的子数组时,把i位置后面的前缀和也考虑进去

② 我们无需创建一个前缀和数组,因为在我们统计的时候我们只用到了i位置前一个位置的前缀合即sum[i-1],sum[i-1]+nums[i]即为sum[i],因此我们只需要用一个sum变量来标记前一个位置的前缀和即可

③为了应对sum【i】能够整除K这一情况,我们在统计次数前,先往哈希表中插入前缀和为0

补充知识:

①同余定理,为什么求【0,i-1】区间内能够多少个前缀和能够整除K与以i为结尾的子数组能够整除K是等价的,这是因为由于同余定理告诉我们(a-b)/p=k余0可得出a%p=b%p,在本题中也就是本来是(sum-x)%k=0得出sum%k=x%k,x即【0,i-1】区间的前缀和

②负数%正数的修正,由于本题中数组的元素存在负数,因此前缀和可能出现负数的情况,所以在前缀和进行取摩的时候,我们需要进行修正,在C++中负数对正数取摩的修正是(原数%p+p)%p

2.3  具体代码

  1. class Solution {
  2. public:
  3. int subarraysDivByK(vector<int>& nums, int k) {
  4. unordered_map<int,int> hash;
  5. int n=nums.size(),sum=0,ret=0;
  6. hash[0]++; //0 这个数的余数
  7. for(int i=1;i<=n-1;i++)
  8. {
  9. sum+=nums[i]; // 算出当前位置的前缀和
  10. ret+=hash[(sum%k+k)%k]; // 修正后的余数并统计结果
  11. hash[(sum%k+k)%k]++; //
  12. }
  13. return ret;
  14. }
  15. };

三、结语

        到此为止,本文关于前缀和(三)内容到此结束了,如有不足之处,欢迎小伙伴们指出呀!

         关注我 _麦麦_分享更多干货:_麦麦_-CSDN博客

         大家的「关注❤️ + 点赞? + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!

        欢迎大家参观我的算法专栏:麦麦的算法专栏

一枚积极学习,乐于分享的苏苏子
QQ名片
注:本文转载自blog.csdn.net的_麦麦_的文章"https://blog.csdn.net/m0_73953114/article/details/145622176"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

113
数据结构与算法
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top