LeetCode刷题系列 -- 974. 和可被 K 整除的子数组

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。

示例 1:

输入:nums = [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]

示例 2:

输入: nums = [5], k = 9

输出: 0

提示:

  • 1 <= nums.length <= 3 * 10^4

  • -10^4 <= nums[i] <= 10^4

  • 2 <= k <= 10^4

974. 和可被 K 整除的子数组 - 力扣(Leetcode)

思路

定义前缀和数组 preSum,若是有子数组 nums[ i ], ..., nums[ j ] 的和为 k 的倍数,那么有
( preSum[ j ] - preSum[ i ] ) % k == 0, 即 preSum[ j ] % k == preSum[ i ]。
定义 map ,其中 key 为前缀和对k的取余,value 为 前缀和对 k 取余的次数。
有两个特殊情况需要考虑:
1. 负数取余 : ( v % k + k) %k
2. 当 preSum[ m ] 取余的结果为 0 时,证明子数组和 nums[ 0 ] + ... + nums[ m ] 为 k 的倍数

c++:

class Solution {
public:
    int subarraysDivByK(vector& nums, int k) {
        vector preSum(nums.size(), 0);
        map tarMap; // key 为前缀和对 k 的取余,value 为 这样的前缀和出现的次数
        int result = 0;

        tarMap[0] = 1;
        for(int i = 0; i < nums.size(); i++) {
            if(i == 0) {
                preSum[i] = nums[i];
            } else {
                preSum[i] = preSum[i-1] + nums[i];
            }

            int key = (preSum[i]%k+k) % k;
           
            if(tarMap.count(key)) {
                tarMap[key] += 1;
            } else {
                tarMap[key] = 1;
            }

            result += (tarMap[key] - 1);
        }

        return result;
    }
};

你可能感兴趣的:(LeetCode,leetcode,算法,数据结构)