leetcode 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

由于数据比较庞大,暴力O(n^2)是行不通的

举例 对于A= [4,5,0,-2,-3,1] K = 5,
前缀和 s = [0, 4, 9, 9, 7, 4, 5] ,然后对每一项取模,得到[0, 4 ,4, 4, 2, 4, 0], 对于K,存在的模从0 ~ K-1。
构件K个元素的数组,索引表示模,值表示模的数量{ 模 : 数量 }
kcnt = [2, 0, 1, 0, 4] 代表在s中有2个元素的模都为0(即0和5),0个元素的模为1, 1个元素的模为2(即7),0个元素的模为3,4个元素的模为4(即4,9,9,4)
先拉出来[4, 9, 9, 7, 4]来看,这里4+5=9,9+0=9,9+(-2-3) = 4。先把7略过,4,9,9,4他们的模都是4,是因为相邻两者之间相加的数是5的倍数(这里可以将-2-3看做一个-5),在这同模的4个数之间任意取出两个数,那么这两个数的差一定是5的倍数,所以存在C(4, 2) = 6中子数组
所以在保证模相同的情况下,取出两个数都可以得到一组答案。对于这个例子,看kcnt,得到C(2, 2) + C(1, 2) + C(4, 2) = 1 + 0 + 6 = 7

需要注意的是负数的取模,(不是取余) 例如 -7 mod 4 = 1;
-7对4取模
-1 * 4 = -4 > -7,
-2 * 4 = -8 < -7;
-7 - (-2 * 4) = 1

class Solution {
public:
    int subarraysDivByK(vector<int>& A, int K) {
        int n = A.size();
        if(n == 0) return 0;
        vector<int> modk(K, 0);
        modk[0]++;
        int presum = 0; //前缀和
        for(int i=0; i<n; i++){
            presum += A[i];
            if(presum >= 0) modk[presum % K]++;
            //注意取模
            else modk[(presum%K + K)%K]++;
        }

        int cnt = 0;
        //C(n, 2);
        for(int i=0; i<K; i++){
            cnt += modk[i] * (modk[i]-1) / 2;
        }
        return cnt;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值