974. Subarray Sums Divisible by K

问题:

给定数组,求连续子数组之和能被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 };
 
原文地址:https://www.cnblogs.com/habibah-chang/p/12997066.html