0%

Leetcode974-Subarray Sums Divisible by K

Description

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

Example

Example 1:

1
2
3
4
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 <= A.length <= 30000
  • -10000 <= A[i] <= 10000
  • 2 <= K <= 10000

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
If a subarray is divisible by K, it has to be a multiple of K

a-b=n*k, a = running total, b = any previous subarray sum, same as original prefix sum problems.

We want to solve for b, so using basic algebra, b=a-n*k

We don't know what n is, so we can get rid of n by modding every element by k
(b%k) = (a%k) - (n*k)%k

since n*k is a multiple of k and k goes into it evenly, the result of the (n *k)%k will be 0

therefore
b%k = a%k

is the same as the formula we defined earlier, a-b=n*k

where b = running total, a = any previous subarray sum

So we just have to see if running total mod k is equal to any previous running total mod k

Solution 1: Prefix + Hash Table

  • Time Complexity: , N = A.length
  • Space Complexity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int subarraysDivByK(int[] A, int K) {
HashMap<Integer, Integer> map = new HashMap<>();
int prefix = 0;
map.put(0, 1);
int res = 0;

for (int x: A){
prefix = (prefix + x % K + K) % K;
res += map.getOrDefault(prefix, 0);
map.put(prefix, map.getOrDefault(prefix, 0) + 1);
}
return res;
}
}

Solution 2: Prefix + Array, faster

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int subarraysDivByK(int[] A, int K) {
int[] count = new int[K];
count[0] = 1;
int prefix = 0, res = 0;
for (int a : A) {
prefix = (prefix + a % K + K) % K;
res += count[prefix]++;
}
return res;
}
}