974.和可被K整除的子数组
前缀和
-
双for肯定超时,通常涉及连续子数组问题的时候,可以使用前缀和来处理。
-
假设
P[i]=A[0]+A[1]+...+A[i]
。则连续子数组的和sum(i,j)
可以写成P[j]-P[i-1]
(0<i<j)
-
判断子数组的和能否被
K
整除的条件为(P[j]-P[i])mod K == 0
,根据同余定理,只要满足P[j] mod K==P[i-1] mod K
即可。 -
当遍历到第i个元素时,统计以i结尾的符合条件的子数组的个数。用一个以前缀和模K的值为键,出现次数为值的哈希表来维护,并且在遍历的同时更新。这样在计算以
i
结尾的符合条件的子数组个数时,根据上面的分析,答案即为[0...i]
中 前缀和模K
也为P[i]mod K
的位置个数,即map[P[i]mod K]
-
注意事项:
- 哈希表初始值
map[0]=1
,考虑了前缀和本身能被K整除的情况。 - java中被除数为负数时取模结果为负数,需纠正:
(sum%k+k)%k
即可解决问题。
- 哈希表初始值
代码
public int subarraysDivByK2(int[] A,int K){
int ans=0,sum=0;
Map<Integer,Integer> map=new HashMap<>();
map.put(0, 1);
for(int num:A){
sum+=num;
//当被除数为负数时取模结果为负数 需要纠正
int m=(sum%K+K)%K;
int same=map.getOrDefault(m, 0);
ans+=same;
map.put(m, same+1);
}
return ans;
}
原文链接: