引言
这两道题非常相似,也是对哈希表运用的考察,两道题合到一起总结一下
560. 和为K的子数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
这道题就是通过逐一统计数组前缀和再通过哈希表的查找来确定所有子数组个数;
这里只需要注意一点就是,前缀和本身就是k的时候需要初始化为1,就这一种情况;
注释在代码里,就不写详细题解了,代码如下:
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
//key为前缀和,value为该和出现的次数
unordered_map<int, int> hash;
//前缀和为0的时候出现次数为一次
hash[0] = 1;
//如果存在pre[i] = pre[i - 1] + k;那么就可以在map里找是否存在pre[i] - k,
//即map中是否存在pre[i - 1]来确定子数组个数
int pre = 0, ans = 0;
for (int i : nums) {
pre += i;
if (hash.find(pre - k) != hash.end()) {
ans += hash[pre - k];
}
hash[pre]++;
}
return ans;
}
};
974. 和可被 K 整除的子数组
给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。
示例:
输入:A = [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]
提示:
1 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000
这一道几乎一模一样,方法都一样,无非就是上一道题的哈希表key值是差,这一道题变成模就可以了;
同样注意初始化,当前缀和本身被 k 整除时初始化为1即可;
额外注意一点,c++取模时如果被除数为负数时取模结果也为负数,所以为了方便运算这里需要一个转化,将结果转化为正数;
代码如下:
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k) {
unordered_map<int, int> hash;
hash[0] = 1;
int ans = 0, pre = 0;
for (int i : nums) {
pre += i;
//当被除数为负数时取模结果为负数,需要改为正数
int mod = (pre % k + k) % k;
if (hash[mod]) {
ans += hash[mod];
}
hash[mod]++;
}
return ans;
}
};
这两道还是需要能够想到哈希表该怎么来用,这也是解题的关键;