leetcode每日一题-974. 和可被 K 整除的子数组

974. 和可被 K 整除的子数组

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subarray-sums-divisible-by-k
思路:
P[I,J]表示[i,j]的数组和,P[I,J] = P[0,J]-P[0,I-1],所以我们可以用一个数组S存储每个位置的和,(S[J]-S[I-1]) mod K == 0,即满足个数加一,但是每计算一个都要与之前的和做比较,可以发现上式可以转换为S[J] mod K == S[I-1] mod K,所以我们可以用数组S记录取模之后的值,然后使用哈希表记录同一个值的次数,已经存在就加一,将次数相加即可,map[0]==1,为了防止第一项即为K得倍数。
例如上式:
S = [4,4,4,2,4,0]=>[0,1,2,0,3,1]=>7
代码:

class Solution {
     
public:
    int subarraysDivByK(vector<int>& A, int K) {
     
        unordered_map<int, int> record = {
     {
     0, 1}};//存储已经出现的值和次数
        int sum = 0, ans = 0;
        for (int elem: A) {
     
            sum += elem;
            int modulus = (sum % K + K) % K;//取模
            //如果之前已经存在
            if (record.count(modulus)) {
     
                ans += record[modulus];
            }
            //对应的值再加一,表示这次过后出现的次数
            ++record[modulus];
        }
        return ans;
    }
};

拓展: int modulus = (sum % K + K) % K;//取模因为数组中存在负数,所以取模的话值也为负数,即使是远小于K的负数,其对K同余后,其负数同余值的绝对值都要小于K,所以加上K后再对K同余就是其正数的同余值

你可能感兴趣的:(leetcode刷题)