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


    https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/

    第一眼,子数组问题,以为是滑动窗口,但是仔细想想做不了。

    然后看了眼数据规模 30000,私以为可以暴力法过,但是死在了第69个测试用例。

    class Solution {
        public int subarraysDivByK(int[] A, int K) {
            int count = 0;
            int temp = 0;
            for(int i = 0; i < A.length; i++){
                for(int j = i; j < A.length; j++){
                    temp += A[j];
                    if(temp % K == 0){
                        count++;
                    }
                }
                temp = 0;
            }
            return count;
        }
    }

    然后瞄了一眼标签,发现哈希表这个tag,再加上这个题有点想前几天做过的前缀和的题,故使用前缀和思想。

    我一开始是用前缀和找到i,j之间的和,然后判断这个和是否能被K取整,但是做出来分析一下时间复杂度还是O(n^2),一样会TLE

    后来实在没办法了,瞄了一眼评论区才发现大佬们用的是余数来判断的。。

        public int subarraysDivByK(int[] A, int K) {
            int count = 0;
            HashMap<Integer,Integer> map = new HashMap<>();
            int temp = 0;
            map.put(0,1);
            for(int i = 0; i < A.length; i++){
                temp += A[i];
                //这个步骤是将负数转换成正数,为什么要这么操作呢?因为小于0的数字,除余之后得到的还是小于0。但是余数为-5 和余数为5其实可以归为一类。
                int curMod = ((temp % K) + K) % K;
                int preMod = map.getOrDefault(curMod,0);
                count += preMod;
                map.put(curMod,map.getOrDefault(curMod,0)+1);
            }
            return count;
        }

    这个其实又是数学问题,我的数学是真的垃圾啊。。

    同余定理:如果两个整数 a, b 满足 (a-b)%K == 0,那么有 a%K == b%K。
    由此可知,如果 i,j 满足 (prefix(j) - prefix(i-1))%K == 0,那么有 prefix(i)%K == prefix(i-1)%K。
    故,可以扫描一遍前缀和 prefix,利用 map 统计所有余数出现的次数,然后遍历 map 利用组合公式C(n,m) = n!/((n-m)!*m!) 来计算答案。
    此时时间复杂度降到了 O(n)。

    这里因为有K这个固定的数,我们就可以将map转换成数组来节省时间

        public int subarraysDivByK2(int[] A, int K) {
            int[] map = new int[K];
            ++map[0];
            int prefix = 0, res = 0;
            for (int a : A) {
                prefix = (a + prefix) % K;
                if (prefix < 0) prefix += K;
                res += map[prefix]++;
            }
            return res;
        }
  • 相关阅读:
    信息安全系统设计基础第一次实验报告
    信息安全系统设计基础第十二周学习总结
    信息安全系统设计基础第十一周学习报告
    信息安全系统设计基础第十周学习报告
    信息安全系统设计基础第九周学习总结
    Arduino智能小车实践学习报告
    信息安全系统设计基础期中总结
    信息安全系统设计基础第七周学习总结
    信息安全系统设计基础第六周学习总结
    信息安全系统设计基础第五周学习总结
  • 原文地址:https://www.cnblogs.com/ZJPaang/p/12970707.html
Copyright © 2020-2023  润新知