[Leetcode 974]连续子数组的前缀和,哈希表
解题思路
凡是“连续子数组求和”问题,都可以套入下面的逻辑公式
- 假设用
s[i][j]
表示连续子数组a[i:j]
的和, 则不难看出s[i][j] = s[0][j] - s[0][i]
; - 当
s[0][i]
与s[0][j]
同时满足某种条件时 =>s[i][j]
可满足某种条件
容易看出在本题中,当(s[0][j] - s[0][i]) % K == 0
时,s[i][j]
就是符合条件的子数组,即
s[0][j] % K == s[0][i] % K
- 记
s[0][i]
为sum
,我们将key = sum%K
作为哈希表的键,值为其出现的次数hash[key] = n
- 如果
hash[key] > 0
,说明存在n个k
使得s[0][k]%K == key
,即存在n
个A[k:i]
可被K
整除 - 特殊情况1,
sum%K == 0
本身满足条件,初始条件hash[0] = 1
- 特殊情况2,
sum%K < 0
,需要转为正数key = (K+sum%K)%K
代码
/**
* @param {number[]} A
* @param {number} K
* @return {number}
*/
var subarraysDivByK = function(A, K) {
let dp = new Array(K).fill(0),sum = 0, ret = 0;
dp[0] = 1;
for (let i=0;i<A.length;i++) {
sum += A[i];
let key = (K+sum%K)%K;// 消除负数
if (dp[key]) {
ret += dp[key];
}
dp[key]++;
}
return ret;
};
相似题目
- 560. 和为K的子数组 -- 将元素求和
sum
作为哈希表的键 - 1371. 每个元音包含偶数次的最长子字符串 -- 将元音字符出现的奇偶次数状态组合作为哈希表的键