class Solution:
def subarraysDivByK(self, nums, K):
count = 0
prefix_mod = 0
mod_count = {0: 1}
for num in nums:
prefix_mod = (prefix_mod + num) % K
# Handle negative mods
prefix_mod = (prefix_mod + K) % K
count += mod_count.get(prefix_mod, 0)
mod_count[prefix_mod] = mod_count.get(prefix_mod, 0) + 1
return count
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int K) {
unordered_map<int, int> mod_count;
mod_count[0] = 1;
int prefix_mod = 0, count = 0;
for (int num : nums) {
prefix_mod = (prefix_mod + num) % K;
if (prefix_mod < 0) prefix_mod += K;
count += mod_count[prefix_mod];
mod_count[prefix_mod]++;
}
return count;
}
};
class Solution {
public int subarraysDivByK(int[] nums, int K) {
Map<Integer, Integer> modCount = new HashMap<>();
modCount.put(0, 1);
int prefixMod = 0, count = 0;
for (int num : nums) {
prefixMod = (prefixMod + num) % K;
if (prefixMod < 0) prefixMod += K;
count += modCount.getOrDefault(prefixMod, 0);
modCount.put(prefixMod, modCount.getOrDefault(prefixMod, 0) + 1);
}
return count;
}
}
var subarraysDivByK = function(nums, K) {
let count = 0;
let prefixMod = 0;
let modCount = {0: 1};
for (let num of nums) {
prefixMod = (prefixMod + num) % K;
if (prefixMod < 0) prefixMod += K;
count += (modCount[prefixMod] || 0);
modCount[prefixMod] = (modCount[prefixMod] || 0) + 1;
}
return count;
};
You are given an array of integers nums
and an integer K
. Your task is to find the total number of contiguous subarrays whose sum is divisible by K
.
nums
).Constraints:
nums.length
≤ 3 × 104nums[i]
≤ 104K
≤ 104
The straightforward way to solve this problem is to consider every possible subarray, compute its sum, and check if it is divisible by K
. However, this brute-force approach would be too slow for large arrays.
To optimize, we need to avoid recalculating sums for overlapping subarrays. A key insight is to use prefix sums: the sum of elements from the start up to a given index. If two prefix sums have the same remainder when divided by K
, the subarray between them is divisible by K
. This is because the difference between the two prefix sums is a multiple of K
.
By tracking how often each remainder occurs, we can efficiently count valid subarrays. This shifts our approach from checking every subarray to counting the frequency of prefix sum remainders.
K
.
K
as the count of that remainder so far. Add this count to the answer.
[0, K-1]
.
0:1
to handle subarrays starting from the beginning.
This approach ensures each element is processed only once, and all lookups and updates are constant time.
Input: nums = [4,5,0,-2,-3,1]
, K = 5
prefix_mod = 0
, mod_count = {0:1}
, count = 0
4
→ prefix_mod = (0 + 4) % 5 = 4
mod_count[4]
not found, count
stays 0. Increment mod_count[4]
to 1.
5
→ prefix_mod = (4 + 5) % 5 = 4
mod_count[4] = 1
, so add 1 to count
(now 1). Increment mod_count[4]
to 2.
0
→ prefix_mod = (4 + 0) % 5 = 4
mod_count[4] = 2
, add 2 to count
(now 3). Increment mod_count[4]
to 3.
-2
→ prefix_mod = (4 + -2) % 5 = 2
mod_count[2]
not found, count
stays 3. Increment mod_count[2]
to 1.
-3
→ prefix_mod = (2 + -3) % 5 = -1 % 5 = 4
4
. mod_count[4] = 3
, add 3 to count
(now 6). Increment mod_count[4]
to 4.
1
→ prefix_mod = (4 + 1) % 5 = 0
mod_count[0] = 1
, add 1 to count
(now 7). Increment mod_count[0]
to 2.
Final answer: 7
nums
.
By leveraging prefix sums and a hash map to track remainders, we efficiently count all subarrays whose sum is divisible by K
. The key insight is recognizing that matching remainders indicate subarrays with sums divisible by K
. This approach reduces the problem from quadratic to linear time, making it both elegant and practical for large inputs.