560. 和为K的子数组 && 974. 和可被 K 整除的子数组 (哈希表)

引言

这两道题非常相似,也是对哈希表运用的考察,两道题合到一起总结一下

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;
    }
};

这两道还是需要能够想到哈希表该怎么来用,这也是解题的关键;

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YXXYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值