代码如下:
import java.util.HashMap;
import java.util.Map;
/**
* 前缀和
*
* 设P[i] = A[0]+A[1]+...+A[i],由题意可得,sum(i,j)可被K整除
* 所以可以转换成(P[j]-P[i-1]) % K == 0,其中(0<i<j),由同余定理可得:
* M = P[j] % K == P[i-1] % K 即可满足条件
*
* 我们可以遍历这个数组,然后用HashMap来记录上面键M的值,随着遍历的过程
* 如果发现后面的键M与前面的键M相同,则这个子区间符合条件
*
* 边界条件是哈希表record.put(0,1),表示取到键M为0,有1个子区间,这样考虑到
* 前缀和本身被K整除的情况
*
* Code by java
*/
class Solution {
public int subarraysDivByK(int[] A, int K) {
Map<Integer, Integer> record = new HashMap<>();
record.put(0, 1); //边界条件
int sum = 0, ans = 0;
for (int elem : A) {
sum += elem; //遍历过程中,依次叠加求和,用于维护前缀和
//防止被除数为负数时,求的键值为,可以采用以下两种方式解决
// int modulus = (sum % K + K) % K; //方法一
int modulus = Math.floorMod(sum, K); //使用向下取整
int same = record.getOrDefault(modulus, 0); //记录当前位置前缀和取模键的值,如果没有则表示为0
ans += same; //更新最终结果
record.put(modulus, same + 1); //维护前缀和,并且算上当前遍历的这个数,所以same+1
}
return ans;
}
public static void main(String[] args) {
Solution a = new Solution();
int[] p = new int[] { 4, 5, 0, -2, -3, 1 };
System.out.println(a.subarraysDivByK(p, 5));
}
}