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

暴力法

计算数组前缀和,使用前缀和遍历数组连续区间。

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        int count = 0;
        int[] sum = new int[A.length + 1];
        //计算前缀之和 
        for(int i = 1; i < sum.length; i++){
            sum[i] = sum[i-1] + A[i-1];
        }
        //遍历所有区间,计算i-j之间的元素之和
        for(int i = 0; i < sum.length; i++){
            for(int j = i+1; j < sum.length; j++){
                if((sum[j] - sum[i])%K == 0) ++count;
            }
        }
        return count;
    }
}

哈希表逐一统计

这题利用了同余定理,如果前缀和与%K余数相同则它们之间的组和一定能构成连续子数组,其和能整除K

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        //键为前缀和%k,值为该余数出现的次数
        HashMap<Integer,Integer> record = new HashMap<>();
        record.put(0,1);//考虑整个数组本身的和整除k的情况
        int sum = 0;//前缀和
        int ans = 0;//答案
        for(int num : A){
            sum += num;
            //java中负数模运算还是负数,因此需要修正
            int mod = (sum % K + K) % K;
            int same = record.getOrDefault(mod,0);
            ans += same;//0 + 1 + 2 + 3 + 1,[4,5,-2,-3,1]
            record.put(mod,same+1);
        }
        return ans;
    }
}

哈希表 单次统计

上面的代码对结果进行了逐一统计计算,下面代码在维护完record表后使用排列组合对结果进行计算。

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        //键为前缀和%k,值为该余数出现的次数
        HashMap<Integer,Integer> record = new HashMap<>();
        record.put(0,1);//考虑整个数组本身的和整除k的情况
        int sum = 0;//前缀和
        int ans = 0;
        //维护record
        for(int num : A){
            sum += num;
            //java中负数模运算还是负数,因此需要修正
            int mod = (sum % K + K) % K;
            record.put(mod,record.getOrDefault(mod,0)+1);
        }
        //使用排列组合,相同余数出现的总次数为entry.getValue,从中取两个进行组合
        for(Map.Entry<Integer,Integer> entry : record.entrySet()){
            ans += (entry.getValue() * (entry.getValue() - 1))/2;
        }
        return ans;
    }
}
posted @ 2020-07-26 11:07  消灭猕猴桃  阅读(59)  评论(0编辑  收藏  举报