前言
个人网站
公众号: 北京程序猿, 网站 : https://yaml.vip
算法题
题干
给定一个整数数组 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
解法
- 暴力解法
- 同余解法, 与Leetcode之523-连续的子数组和很相似
Java代码
public int subArraysDivByK(int[] A, int K) {
Map<Integer, Integer> map = new HashMap<>(16);
int sum = 0;
for (int ele : A) {
sum += ele;
sum %= K;
if (sum < 0) {
sum += K;
}
if (map.containsKey(sum)) {
map.put(sum, map.get(sum) + 1);
} else {
map.put(sum, 1);
}
}
int count = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int val = entry.getValue();
count += val * (val - 1) / 2;
if (entry.getKey() == 0) {
count += val;
}
}
return count;
}
代码解析
- 第2行代码新建HashMap, key为被K整除之后的正余数, value为个数。
- 第7-9行代码, 是将余数由负数转变为正数。
- 比如sum%3余数范围是{-2,-1,0,1,2}, 转换之后范围是{0,1,2}。
- 比如-9=(-2) * 4 + (-1), -1是余数。
- 同时-9=(-3) * 4 + 3, 3也是余数, 这个3可以由余数-1加上除数4得到。
- 第19行代码表示相同余数的sum有val个, 那么每个余数对应有多少个子数组能被K整除。
- 好比一条直线上N个不同的点,求线段的条数。
- 解法就是C(N,2), 从N个点中取2个点的总取法。
- 第20-22行表示直接被K整除的情况。
本文著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请于文首标明作者姓名,保持文章完整性,并附上出处和文章链接!未按规范转载者,作者保留追究相应责任的权利!
作者:北京程序猿
链接: 和可被K整除的子数组