leetcode 974

和可被 K 整除的子数组

Posted by Static on May 27, 2020

题目链接:https://leetcode-cn.com/problems/subarray-sums-divisible-by-k

题目描述


分析

1. 嵌套for循环

遍历数组寻找能整除5的数之和,但是时间复杂度不符合题目要求

2. 同余定理

同余定理:[P(j)-P(i-1)]%K==0 <=> P(j)%K==P(i-1)%K,P(j)=a[0]+a[1+]..+a[j]

将余数和余数出现的次数存在map中,余数次数大于0之和即是题目答案


代码实现

public enum Q974 {
    instance;
    // O(n^2)
    public int subarraysDivByK(int[] A, int K) {
        int count=0;
        for(int i=0;i<A.length;i++){
            int sum=0;
            for(int j=i;j<A.length;j++){
                sum+=A[j];
                if(sum%K==0){
                    count++;
                }
            }
        }
        return count;
    }

    // O(n)
    public int subarraysDivByK1(int[] A, int K) {
        // 同余定理:[P(j)-P(i-1)]%K==0 <=> P(j)%K==P(i-1)%K,P(j)=a[0]+a[1+]..+a[j]

        // k:余数;v:次数(k:3,v:1 余数是3的K整除的数是1)
        Map<Integer,Integer> map = new HashMap<>();
        // 0%K==0
        map.put(0,1);
        int sum=0,count=0;
        for(int i:A){
            sum+=i;
            int remainder=(sum%K+K)%K;//sum=13,K=5:-13%5=-3,-3+5=2,2%5=3
            int remainderCount=map.getOrDefault(remainder,0);
            count+=remainderCount;
            map.put(remainder,remainderCount+1);
        }
        return count;
    }

    public static void main(String[] args) {
        // assert 7
        SystemUtil.print(Q974.instance.subarraysDivByK1(new int[]{4,5,0,-2,-3,1},5));
    }
}