这题计算前缀和,根据前缀和可以得到子数组的和,使用同余定理:下述(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
遍历过程:
计算前缀和 pre( j ) % k
当pre(j) % k 在哈希表中已存在,则说明此时存在 i 满足 pre(j) % k == pre(i) % k ( i < j )
HashMap里,已知Key,可以取到Value 即i的值, 最后 判断 j - i >= 2 是否成立 即可 ;j-i>=2是为了判断子数组长度是否大于等于2
因在计算 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;
}
原文:https://www.cnblogs.com/kimblogs/p/14847299.html