GuilinDev

Lc0974

05 August 2008

974. Subarray Sums Divisible by K

给定一个整数数组 nums 和一个整数 k,返回总和可被 k 整除的非空子数组的数量。

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

define sum[i, j] as sum from nums[i] to nums[j] for 0 < i < j,

sum[i + 1, j]

= sum[0, j] - sum[0, i]

= q1 * K + r1 - (q2 * K + r2)

= (q1 - q2) * k + (r1 - r2)

so sum[i + 1, j] is divisible by K if r1 == r2

We calculate all possible r’s and map them to their counts, map[r] = count, there are two situations:

r != 0, then count * (count - 1) / 2 subarrays found

r == 0, the sum itself is divisible by k, thencount subarrays found

Please note that when calculate sum % K for sum < 0, we keep adding K to sum until sum is above 0 then mod K.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
    public int subarraysDivByK(int[] A, int K) {
        int count = 0;
        
        // Map remainder to its frequency
        Map<Integer, Integer> rToFreq = new HashMap<>();
        
        // Accumulative sum
        int accSum = 0;
        for (int num : A) { 
            accSum += num;
            while (accSum < 0) {
                accSum += K;
            }
            
            int r = (accSum % K + K) % K;
            rToFreq.put(r, rToFreq.getOrDefault(r, 0) + 1);
        }
        
        // For subarrays starting from the first element, and share the same remainder
        for (int freq : rToFreq.values()) {
            if (freq > 1) {
                count += freq * (freq - 1) / 2;
            }
        }
        
        // For subarrays starting from the first element, and sum divisible by k
        count += rToFreq.getOrDefault(0, 0);
        
        return count;
    }
}