一、题目描述:
leetcode-cn.com/problems/su… 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。 ****示例 1:
输入:A = [4,5,0,-2,-3,1], K = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
二、思路分析:
- 前缀和 + 排列组合
- 1.先求出数组的前缀和 若是 (prefix(j)-prefix(i)) mod K === 0 则找到一个解
- 2.(prefix(j)-prefix(i)) mod K === 0 等价于 prefix(j) mod K = prefix(i) mod K
- 3.对prefix求余数得prefixSumMod
- 4.若prefixSumMod中有n个相同的余数,则这n个中随便两个都可以组成一个子数组使和可被K整除
- 5.其中这个这n个相同的余数就有Cn2种组合,n*(n-1)/2
- 6.负数的余数可能为负数要转为整数(prefixSumMod[i] % K + K) % K
三、AC 代码:
/**
* @param {number[]} A
* @param {number} K
* @return {number}
*/
var subarraysDivByK = function (A, K) {
const prefixSum = [0]
for (let i = 0; i < A.length; i++) {
prefixSum[i + 1] = A[i] + prefixSum[i]
}
const prefixSumMod = prefixSum.map(item => {
return (item % K + K) % K
})
const map = {}
for (let i = 1; i < prefixSumMod.length; i++) {
if (map[prefixSumMod[i]] === undefined) {
map[prefixSumMod[i]] = 1
} else {
map[prefixSumMod[i]] += 1
}
}
let counter = 0
for (let key in map) {
if (key == 0) {
counter += map[key] + map[key] * (map[key] - 1) / 2
} else {
counter += map[key] * (map[key] - 1) / 2
}
}
return counter
};
四、总结:
- 画图画图,把图画出来有助于思考😭