这题计算前缀和,根据前缀和可以得到子数组的和,使用同余定理:下述(2)简化判断倍数的过程

同余定理

(1)(m-n)%k==0   -->  m%k==0  n%k==0

(2)if  a =b+c  then a%k =(b+c)%k =(b%k+c%k)%k

使用(2)简化前缀和,(2)证明当前前缀和%k对之后的前缀和%k没有影响

哈希表

存储 <key ,value>  :key = pre[i] %k  , value=i

遍历过程

  1. 计算前缀和 pre( j ) % k

  2. 当pre(j) % k 在哈希表中已存在,则说明此时存在 i 满足 pre(j) % k == pre(i) % k ( i < j )

HashMap里,已知Key,可以取到Value 即i的值, 最后 判断 j - i >= 2 是否成立 即可    ;j-i>=2是为了判断子数组长度是否大于等于2

  1. 当 pre(j) % k 不存在于哈希表,则将 (pre(j) % k, j ) 存入哈希表

因在计算 pre(i) = (pre(i-1) + nums[i]) % k 时,pre(i) 只与上一个状态有关

故可以直接用变量pre 替代数组。 那么 求前缀和 % k 的公式就简化为 题解代码中的 remainder = (remainder + nums[i]) % k;

code:(官方题解)

链接:https://leetcode-cn.com/problems/continuous-subarray-sum/solution/lian-xu-de-zi-shu-zu-he-by-leetcode-solu-rdzi/

    public boolean checkSubarraySum(int[] nums, int k) {
        int m = nums.length;
        if (m < 2) {
            return false;
        }
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(0, -1);
        int remainder = 0;
        for (int i = 0; i < m; i++) {
            remainder = (remainder + nums[i]) % k;
            if (map.containsKey(remainder)) {
                int prevIndex = map.get(remainder);
                if (i - prevIndex >= 2) {
                    return true;
                }
            } else {
                map.put(remainder, i);
            }
        }
        return false;
    }

  

 

posted on 2021-06-03 21:31  水未央  阅读(59)  评论(0编辑  收藏  举报