题目描述
给定一个整数数组 nums
和一个整数 k
,返回其中元素之和可被 k
整除的(连续、非空) 子数组 的数目。
子数组 是数组的 连续 部分。
示例 :
输入:nums = [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]
思路
前缀和这里就不过多赘述,本思路主要解释不同的语言负数取模的值不一定相同,有的语言为负数,对于这种情况需要的特殊处理
(sum % k + k) % k;
(sum % K + K) % K 其实就是将负余数转为正余数,但并不是简单的去掉负号,而是增加一个 k 的步长,比如 -7 % 4,它的负余数为 -3,加上步长 4 之后,就转为正余数 1 了;即对负数有两种计算余数的方式,第一是 -7 = -14 + (-3) 此时余数为 -3,第二是 7 = -24 + 1 此时余数为 1。而并不是说 -3 装为 3,而是 -3 转为 1;这样针对类似于数组 [-7,8],k = 4 的情况时,就有 -7 % 4 为 1,(-7+8)% 4 为 1,两者余数相等,所以(-7+8)-(-7)为 8 可以整除 4,这样不会漏掉 8 这个数了
解题代码
class Solution {
public int subarraysDivByK(int[] nums, int k) {
Map<Integer, Integer> record = new HashMap<Integer, Integer>();
record.put(0, 1);
int sum = 0, ans = 0;
for (int elem : nums) {
sum += elem;
// 注意 Java 取模的特殊性,当被除数为负数时取模结果为负数,需要纠正
int modulus = (sum % k + k) % k;
int same = record.getOrDefault(modulus, 0);
ans += same;
record.put(modulus, same + 1);
}
return ans;
}
}