题解
知识点
通常,涉及连续子数组问题的时候,我们使用前缀和来解决。
我们令 P[i] = A[0] + A[1] + … + A[i]。那么每个连续子数组的和
s
u
m
(
i
,
j
)
=
P
[
j
]
−
P
[
i
−
1
]
(
其
中
0
<
i
<
j
)
sum(i, j) = P[j] - P[i-1] \;(其中0 < i < j)
sum(i,j)=P[j]−P[i−1](其中0<i<j), 判断连续子数组的和能否被 K 整除就等价于
(
P
[
j
]
−
P
[
i
−
1
]
)
m
o
d
K
=
=
0
)
(P[j] - P[i-1])\, mod\, K == 0)
(P[j]−P[i−1])modK==0), 根据同余定理 ,只要
P
[
j
]
m
o
d
K
=
=
P
[
i
−
1
]
m
o
d
K
P[j] \,mod \,K == P[i-1]\, mod\, K
P[j]modK==P[i−1]modK, 就可以满足条件。
方法一:哈希表+逐一统计
思路
对数组进行遍历,在遍历的同时统计答案。当遍历数组的第 i 个元素时,统计数组以 i 结尾符合条件的子数组的个数。我们维护一个以前缀和 mod K 的值为键,出现次数为值的哈希表 r e c o r d record record,在遍历的同时更新哈希表。那么以 i 结尾的符合条件的子数组个数即为 r e c o r d [ P [ i ] m o d K ] record[P[i] \,mod\, K] record[P[i]modK]。
Code
cpp
class Solution {
public:
int subarraysDivByK(vector<int>& A, int K) {
unordered_map<int, int> record = {{0, 1}};
int ans = 0; int sum = 0;
for (int i: A){
sum = sum + i;
int modulus = (sum%K + K) % K;
if (record.count(modulus)){
ans = ans + record[modulus];
}
record[modulus]++;
}
return ans;
}
};
python
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
record = {0: 1}
sum_fro, ans = 0, 0
for i in A:
sum_fro += i
modulus = sum_fro % K
nums = record.get(modulus, 0)
ans += nums
record[modulus] = nums + 1
return ans
方法二:哈希表 + 单次统计
思路
依据方法一中的思路,在遍历数组时只维护哈希表。在遍历结束后,我们遍历哈希表,从排列组合的角度统计答案。
对于哈希表中的每个键值对
(
x
,
v
x
)
(x, v_x)
(x,vx),它表示前缀和 mod K 的值
x
x
x 出现了
v
x
v_x
vx次。那么这些满足条件的位置两两之间都可以构成 被 K 整除的连续子数组,数量为
(
v
x
2
)
=
v
x
∗
(
v
x
−
1
)
2
\begin{pmatrix}v_x\\2\end{pmatrix} = \dfrac{v_x * (v_x-1)}{2}
(vx2)=2vx∗(vx−1) 个可被 K 整除的连续子数组。
Code
cpp
class Solution {
public:
int subarraysDivByK(vector<int>& A, int K) {
unordered_map<int, int> record = {{0, 1}};
int ans = 0; int sum = 0;
for (int i: A){
sum = sum + i;
int modulus = (sum%K + K) % K;
record[modulus]++;
}
for (auto [x, vx]: record){
ans = ans + vx * (vx - 1) / 2;
}
return ans;
}
};
python
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
record = {0: 1}
sum_fro, ans = 0, 0
for i in A:
sum_fro += i
modulus = sum_fro % K
record[modulus] = record.get(modulus, 0) + 1
for x, vx in record.items():
ans += vx * (vx - 1) // 2
return ans