问题:
给定数组,求连续子数组之和能被K整除的,子数组个数。
Example 1: Input: A = [4,5,0,-2,-3,1], K = 5 Output: 7 Explanation: There are 7 subarrays with a sum divisible by K = 5: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3] Note: 1 <= A.length <= 30000 -10000 <= A[i] <= 10000 2 <= K <= 10000
解法:
PreSum 类似:前缀求和法
求[i~j]的sum 即为 presum[j] - presum[i-1]
对于本问题:
presum[j]-presum[i]=n*K :数组[i~j]的sum能被K整除。
那么:presum[i]=presum[j]-n*K
由于n可以为0,1,2...∞,任意数都可,不定,我们可以对上式进行mod运算,去掉n
presum[i]%K = presum[j]%K - n*K%K
即:
presum[i]%K = presum[j]%K - 0
我们要求 以j为结尾,数组[i~j]的sum能被K整除 的数组个数。
(由于当前 到 j 的前缀数组 被K整除后 余数为 presum[j]%K)
=找 前缀和被K整除后 (presum[j]%K的互补余数)余数为 presum[i]%K 的数组个数。
又因为
presum[i]%K = presum[j]%K - 0
因此,我们只要找,余数为(他自己) presum[j]%K 的数组个数。
因此,类比PreSum构建的presum计数数据结构,
我们构建presum[i]%K的计数数据结构。premodcount
premodcount[x]
用来保存元素之和%K的结果为 x 的前缀子数组个数。
遍历数组元素,对当前元素A[j],求Fun=Sum(A[0]+...A[j])%K
寻找
到目前为止,余数为(他自己) presum[j]%K 的数组个数。
=premodcount(Fun)。
并更新 计数数据结构 premodcount
计数+1:premodcount[Fun]++;
代码参考:
1 class Solution { 2 public: 3 int subarraysDivByK(vector<int>& A, int K) { 4 vector<int> premodcount(K);//prevalue, rescout 5 int res=0; 6 int presum=0; 7 premodcount[0]=1; 8 for(int i=0; i<A.size(); i++){ 9 presum=(presum+A[i]%K+K)%K; 10 res+=premodcount[presum]; 11 premodcount[presum]++; 12 } 13 return res; 14 } 15 };