Count the number of subarrays whose sum is divisible by k
Medium
📘 Problem Statement
Given an integer array nums
and an integer k
, return the number of non-empty subarrays that have a sum divisible by k.
🔍 Example
Example 1:
Input:
nums = [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]
🛠️ Solution
❌ Brute Force Approach (Inefficient)
- Try all possible subarrays and count how many of them have sum divisible by
k
def numberOfSubarrays(nums, k):
count = 0
n = len(nums)
for i in range(n):
total = 0
for j in range(i, n):
total += nums[j]
if total % k == 0:
count += 1
return count
The total complexity of this solution is . Not efficient for large arrays.
⚡ Optimized Approach: Prefix Sum
💡 Key Idea:
We know:
If
prefix_sum[j] % k == prefix_sum[i - 1] % k
, then thesubarray [i..j]
is divisible byk
.
📘 Why This Works ?
-
sum(i..j) = prefix_sum[j] - prefix_sum[i - 1]
-
so ,
(prefix_sum[j] - prefix_sum[i - 1]) % k == 0 → prefix_sum[j] % k == prefix_sum[i - 1] % k
✅ Strategy:
- Track
prefix_sum % k
at each index. - Use a hashmap to count how many times each mod value has appeared.
- For current
prefix_sum
mod, addcount_map[mod]
to the result. - Initialize count_map = {0: 1} to handle subarrays starting from index 0.
def subarraysDivByK(nums, k):
subarray_count = 0
num_so_far = 0
freq_count = {0 : 1} # For subarrays starting at index 0
for num in nums:
num_so_far += num # prefix sum
remainder = num_so_far % k
subarray_count += freq_count.get(remainder, 0)
freq_count[remainder] = freq_count.get(remainder, 0) + 1
return subarray_count
⏱️ Time & Space Complexity
Operation | Complexity |
---|---|
Time | |
Space |