[LeetCode974. 和可被 K 整除的子数组] | 刷题打卡

222 阅读1分钟

一、题目描述:

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


};

四、总结:

  • 画图画图,把图画出来有助于思考😭