974.和可被K整除的子数组

image-20200530220934992

前缀和

官方思路

  • 双for肯定超时,通常涉及连续子数组问题的时候,可以使用前缀和来处理。

  • 假设P[i]=A[0]+A[1]+...+A[i]。则连续子数组的和sum(i,j)可以写成P[j]-P[i-1] (0<i<j)

  • 判断子数组的和能否被K整除的条件为 (P[j]-P[i])mod K == 0,根据同余定理,只要满足

    P[j] mod K==P[i-1] mod K 即可。

  • 当遍历到第i个元素时,统计以i结尾的符合条件的子数组的个数。用一个以前缀和模K的值为键,出现次数为值的哈希表来维护,并且在遍历的同时更新。这样在计算以 i 结尾的符合条件的子数组个数时,根据上面的分析,答案即为[0...i] 中 前缀和模 K 也为 P[i]mod K 的位置个数,即 map[P[i]mod K]

  • 注意事项:

    • 哈希表初始值 map[0]=1,考虑了前缀和本身能被K整除的情况。
    • java中被除数为负数时取模结果为负数,需纠正: (sum%k+k)%k 即可解决问题。

代码

public int subarraysDivByK2(int[] A,int K){
        int ans=0,sum=0;
        Map<Integer,Integer> map=new HashMap<>();
        map.put(0, 1);
        for(int num:A){
            sum+=num;
            //当被除数为负数时取模结果为负数  需要纠正
            int m=(sum%K+K)%K;
            int same=map.getOrDefault(m, 0);
            ans+=same;
            map.put(m, same+1);
        }
        return ans;
    }

原文链接:

官方题解

原文地址:https://www.cnblogs.com/yh-simon/p/13021248.html