给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。

示例:
输入:A = [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]

提示:
1 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000

1 暴力解法

开始拿到题,第一反应是两层循环,外层 i 从 0-N,内层 j 从 i 到 N,外层里用一个sum来求和,用sum%K==0来判断能否整除。这样时间复杂度是O(n^2),果然超时了。

看了别人的答案,依然理解不了,之后才知道要用前缀和的方法来达到O(n)的复杂度。

2 前缀和解法

我们首先定义一个前缀和数组 prefix,prefix[0]=0,prefix[1]=A[0],prefix[2]=prefix[1]+A[1]……总之,prefix就是从第0个元素开始加和的结果。

我们这样得到 prefix :

int subarraysDivByK(vector<int>& A, int K) {int N = A.size();vector<int> prefix(N+1);for (int i=0;i<N;++i){prefix[i+1]=prefix[i]+A[i];}

以 A=[4,5,0,-2,-3,1],K=5 为例,然后我们得到下表:

index 0 1 2 3 4 5
A 4 5 0 -2 -3 1
prefix 0 4 9 9 7 4 5
prefix%5 0 4 4 4 3 4 0

其中 prefix%K 就是 prefix 对 5 求余的结果。

诀窍就在这里,我们观察 index 1-3 中 prefix%5 出现的3个4:
prefix[1] = ΣA[0]
prefix[2] = ΣA[0-1]

而ΣA[0]%5 = ΣA[0-1]%5,这就表明Σ0和Σ0-1的差值必然是5的倍数,得到
ΣA[0-1] - ΣA[0] → A[1]%5==0
→ {5}是一个符合集合。

同理,在第1个4和第3个4之间:
prefix[1] = ΣA[0]
prefix[3] = ΣA[0-2]
→ ΣA[0-2] - ΣA[0] → ΣA[1-2]%5==0
→ {5,0}是一个符合集合。

同理,在第2个4和第3个4之间,夹了一个A[2]=0:
→ {0}是一个符合集合。

这样,我们可以知道,当同样的数字出现2次时,表明1个符合集合出现了;当同样的数字出现3次时,表明3个符合集合出现了。这说明在4出现的3次中,两两一对,共有3对代表了3个符合的集合。

设出现4的次数为n,则符合的集合数量为C(n,2),C(n,2)=n!/((n-2)!*2)=n*(n-1)/2。

在上面的例子中:

  • 0出现了2次,result加上1;
  • 3出现了1次,不能配对,所以result不变;
  • 4出现了4次,result加上C(4,2)=6;

最终符合的集合数量为7。

代码:

    vector<int> cnt(K);for (auto n:prefix){int num=(n%K+K)%K;cnt[num]++;}int ret=0;for (auto n:cnt)ret+=n*(n-1)/2;return ret;

这里我们用数组 cnt 来记录余数为 0-4 的次数。
至于 (n%K+K)%K 的目的在于将余数为负数的转化为正数,例如 n%5 in {-4,-3,-2,-1,0,1,2,3,4},则 (n%5+5)%5 in {0,1,2,3,4}。

这段代码和上面的那段连起来就是完整的解答了。

参考文献
[1] LeetCode 525.连续数组
https://www.cnblogs.com/geek1116/p/9389236.html

leetcode 974. 和可被 K 整除的子数组 详解相关推荐

  1. 【算法】leetcode 974. 和可被 K 整除的子数组(前缀和思想)

    前言 前缀和相关: leetcode 974. 和可被 K 整除的子数组(前缀和思想) leetcode 560. 和为K的子数组(前缀和思想II) 问题来源 974. 和可被 K 整除的子数组 给定 ...

  2. LeetCode 974. 和可被 K 整除的子数组 | Python

    974. 和可被 K 整除的子数组 题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/subarray-sums-divisible-by-k 题目 ...

  3. Leetcode 974. 和可被 K 整除的子数组 前缀和

    原题链接:Leetcode 974. 和可被 K 整除的子数组 class Solution {public:int subarraysDivByK(vector<int>& nu ...

  4. LeetCode 974. 和可被 K 整除的子数组(哈希map)

    1. 题目 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例: 输入:A = [4,5,0,-2,-3,1], K = 5 输出:7 解释: 有 7 个子数组满 ...

  5. 560. 和为K的子数组 974. 和可被 K 整除的子数组 (哈希表)

    引言 这两道题非常相似,也是对哈希表运用的考察,两道题合到一起总结一下 560. 和为K的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入 ...

  6. ⭐算法入门⭐《前缀和》中等02 —— LeetCode 974. 和可被 K 整除的子数组

    文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 1)初始化前缀和 2)哈希表统计 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题 ...

  7. LeetCode 862. 和至少为 K 的最短子数组(前缀和+deque单调栈)

    1. 题目 返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K . 如果没有和至少为 K 的非空子数组,返回 -1 . 示例 1: 输入:A = [1], K = 1 输出:1示例 2: ...

  8. LeetCode——974.和可被K整除的子数组

    这几天力扣总算是放我这个菜鸡一马,来了一些中等难度题.和可被K整除的子数组,一看到反正最近脑子里都是双指针.滑动窗.前缀和.动态规划之类的东西.话不多说,赶紧看一看今天的题. 974.和可被K整除的子 ...

  9. leetcode *974. 和可被 K 整除的子数组(2020.5.27)

    [题目]*974. 和可被 K 整除的子数组 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例: 输入:A = [4,5,0,-2,-3,1], K = 5 输 ...

最新文章

  1. 快速排序的递归和非递归
  2. how to check unsolved conflicts file list in git merge?
  3. 【Win10 UWP】URI Scheme(二):自定义协议的处理和适用场景
  4. redhat和ubuntu上部署本地源
  5. 这些棘手的Java面试题,答案你都知道吗?
  6. 转载[POJ题型分类]
  7. JNI开发笔记(八)--Java读取txt文件进行JNI测试
  8. 数据库连接配置 app.config web.config
  9. Javascript自定义类
  10. 高通总裁安蒙在“GSMA Thrive”中分享了哪些关键信息?
  11. 高考数据分析和读书感悟
  12. 三节串联锂电池充电管理芯片,IC电路图,BOM表
  13. CC攻击防御策略详解,效果显著
  14. 博士申请 | 阿尔伯塔大学招收人工智能方向全奖博士生、硕士生
  15. cesium 矢量图 编辑_openlayers添加、删除矢量图,多边形
  16. [4G+5G专题-137]: 终端 - 射频前端(滤波器、功率放大器)详解
  17. css图片菜鸟教程,css 常用样式(分享)
  18. 数据安全建设中合规管理措施
  19. MIT 6.824涉及的部分论文翻译
  20. (闲杂笔记1) 控件尺寸与像素关系

热门文章

  1. [你必须知道的.NET] 开篇有益-------这是一个系列,文章中有后面章节的连接
  2. 关于 某讯QQ群的群文件上传和下载出现错误-134 的解决方法
  3. PMO和项目经理必须掌握的战略制定与执行的思路和方法
  4. 【从零开始的C语言】初阶 数组应用之 扫雷
  5. 电路板脑洞微距大赏!
  6. 通过扔一个诱饵进行无源无监督域适应
  7. 信也科技股权曝光:顾少丰持股29.4% 有63.7%投票权
  8. 机械键盘按键不灵敏怎么办、机械键盘按键坏了怎么办、维修机械键盘
  9. 服务器虚拟化课程总结,虚拟化与云计算课程总结报告
  10. 小学教师使用计算机责任书,计算机安全管理责任书.doc