在做题在学习(60):和可被K整除的子数组

974. 和可被 K 整除的子数组 - 力扣(LeetCode)

解法:前缀和 + 哈希表 + 同余定理

同余定理:

而此题要求返回能被k整除(%k = 0)的子数组的个数,如下图:

把问题转化为——> 有多少个前缀和的余数 == sum%k ???

细节

1.c++中的[整数 % 负数]转化

负数 % 正数  = 负数  ——修正——> a % p + p  ——正负统一——> (a % p + p) % p

2.默认哈希表中 hash[0] = 1

因为0 % k 一定 == 0

3.前缀和的余数什么时候丢入哈希表?


因为放进去的是前缀和的余数,放[0,i]的话,到了[0,i+1]就会重复,所以到i下标时,先放入[0,i-1]的前缀和的余数,再加入自己。

4.不用真的创建一个前缀和数组


dp[i] = sum + nums[i]  ,所以只需要一个sum代表前一次的前缀和,每次算完前缀和,把sum更新就行了。

class Solution 
{
public:
    int subarraysDivByK(vector<int>& nums, int k) 
    {
        unordered_map<int,int> hash;
        hash[0] = 1;
        int sum = 0,count = 0,rest = 0;
        for(auto e : nums)
        {
            sum += e;
            rest = (sum % k + k) % k;
            //这里的判断就是先判断前面位置的前缀和的余数
            if(hash.count(rest))
                count += hash[rest];
            //到这里,再把当前i位置的前缀和的余数放入哈希表
            hash[rest]++;
        }
        return count;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值