leetcode974. Subarray Sums Divisible by K

Given an array A of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by K.

Example 1:

Input: A = [4,5,0,-2,-3,1], K = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by
			 K = 5:
			 [4, 5, 0, -2, -3, 1], [5], [5, 0],
			 [5, 0, -2, -3], [0], [0, -2, -3], 
			 [-2, -3]

Note:

1.1 <= A.length <= 30000
2.-10000 <= A[i] <= 10000
3.2 <= K <= 10000

给定一个集合,求这个集合中子集的个数,其中对子集的要求是子集中元素的和能被k整除。
记数组pre[i+1]表示前 i 位元素的和mod k 的结果,且规定pre[0]=0。
现假设pre数组中有两个位置 i , j (1<=i<j)上的结果相同,即表示原集合中前 i-1 位和前 j-1 位元素的和 mod k 的值相同,易知从 i-1 到 j-1 位构成的子集中元素的和一定能被 k 整除。
利用这一结论,现只需要统计数组前缀和余数相同的个数,再从余数相同的位置上任选两个位置构成子集,并计算个数
在这里插入图片描述
如上图所示,若计算这个集合中子集个数,只需计算分别从前缀和求余结果为 0 和 4 的位置上,可以挑选出多少对不同的组合,这一结果可以利用组合数求出
Ps:注意前缀和为负的情况,c++中对其求余仍未负数


class Solution {
private:
    vector<int> num;
    vector<int> pre;
public:
    int subarraysDivByK(vector<int>& A, int k) {
        int len=A.size();
        num.resize(k+5,0);
        pre.push_back(0);
        
        for(register int i=0;i<len;i++)
            pre.push_back(pre[i]+A[i]);
        for(auto ele : pre)
            num[(ele%k+k)%k]++;
        
        int ans=0;
        for(register int i=0;i<k;i++){
            ans+=num[i]*(num[i]-1)/2;
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/white_156/article/details/86565714