974.Subarray Sums Divisible by K¶
Tags: Medium
Hash Table
Links: https://leetcode.com/problems/subarray-sums-divisible-by-k/
Given an array A
of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by 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
题意是给定一个序列,求其连续子数组使子数组和能够整除K,很显然求连续子数组的和需要利用前缀和的方法。那么接下来就是如何判断子数组和可以整除K了。
假如某一区间段[i,j]
的子数组和可以整除K,那么表达式就是:
$$
\left(\text{prefixSum}[j] - \text{prefixSum}[i - 1] \right) \% K == 0 \
\text{prefixSum}[j] \% K == \text{prefixSum}[i - 1] \% K
$$
也就意味着假如前缀和下标为j
,那么需要计算从0-j-1
这些前缀和里面,对K
取模和prefixSum[j]
相等的个数,既然是取模,那么我们就可以开一个长度为K
的数组,并且要保证余数在0-K-1
之间,每次只需要把在HashTable
里的个数加上即可。
时间复杂度O(n),空间复杂度O(K)
class Solution {
public:
int subarraysDivByK(vector<int>& A, int K) {
std::ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n = A.size();
vector<int> HashTable(K, 0);
HashTable[0] = 1;
int cnt = 0; //记录总数
int sum = 0; //记录前缀和
for (int i = 0; i < n; ++i) {
sum = ((sum + A[i]) % K + K) % K; //将余数映射到0-K-1
if (HashTable[sum] != 0) cnt += HashTable[sum];
++HashTable[sum];
}
return cnt;
}
};