目录
力扣974. 和可被 K 整除的子数组
解析代码
974. 和可被 K 整除的子数组
难度 中等
给定一个整数数组 nums
和一个整数 k
,返回其中元素之和可被 k
整除的(连续、非空) 子数组 的数目。
子数组 是数组的 连续 部分。
示例 1:
输入:nums = [4,5,0,-2,-3,1], k = 5 输出:7 解释: 有 7 个子数组满足其元素之和可被 k = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:
输入: nums = [5], k = 9 输出: 0
提示:
1 <= nums.length <= 3 * 10^4
-10^4 <= nums[i] <= 10^4
2 <= k <= 10^4
class Solution {
public:
int subarraysDivByK(vector& nums, int k) {
}
};
和上一篇博客力扣560. 和为 K 的子数组的原理一样,只是要多了解两个知识:
①同余定理。②C++对负数取模的修正。
同余定理:数论中的重要概念。给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b(mod m)。对模m同余是整数的一个等价关系(即a % m == b % m)。
数学中的取余法则,即两个数取余,余数总是为正数。
C++/Java中负数对正数取余的结果是负数,所以要修正:
C++取模:当被除数为负数时取模结果为负数,需要纠正 -> (x % k + k) % k;
如C++中 -10 % 7 = -3(-10 + 7 * 1 = 3),而数学中 -10 % 7 = 4(-10 + 7 * 2 = 4)
所以在C++中要手动修正成-> (-10 % 7 + 7)% 7 = 4。
理解上面两个知识之后代码就和上一篇博客力扣560. 和为 K 的子数组的差不多一样了:
class Solution {
public:
int subarraysDivByK(vector& nums, int k) {
int n = nums.size(), sum = 0, ret = 0;;
unordered_map hash(n); // 左存前缀和对k取模的余数,右存前缀和出现次数
hash[0 % k] = 1;
for(int i = 0; i < n; ++i)
{
sum += nums[i];
int remainder = (sum % k + k) % k;
if(hash[remainder] != 0)
{
ret += hash[remainder];
}
hash[remainder]++;
}
return ret;
}
};