
Problem Statement
The task is to count the number of contiguous subarrays within an integer array nums, where the sum of the elements in the subarray is divisible by a given integer k. The elements in the array, as well as the subarrays derived from it, can take on any integer value, positive or negative. Understanding that a "subarray" refers to a sequence of one or more elements that are contiguous segments of the main array, the solution should efficiently determine the count of such subarrays where the sum meets the divisibility criterion.
Examples
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]
Example 2
Input:
nums = [5], k = 9
Output:
0
Constraints
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 1042 <= k <= 104
Approach and Intuition
The problem can be approached by focusing on the sum of subarrays and checking for divisibility by k. Here's the step-by-step plan:
Utilize a Hash Map for Frequency Count of Remainders: As you iterate through the array, for each element, maintain a cumulative sum. For each new cumulative sum, compute the remainder of this sum when divided by
k. Store and update the frequency of each unique remainder in a hash map.Understanding Remainder Behavior: The remainder, when divided by
k, could potentially be negative (if the numbers innumsare negative andkis positive, for example). Volatility in remainder signs can be normalized by adjusting remainders: if a remainder is negative, simply addkto it to make it positive.Leverage the Pigeonhole and Prefix Sum Principle: The primary insight here leans on the idea of prefix sums. Specifically, if two prefix sums yield the same remainder upon division by
k, then the elements lying between these two prefixes sum up to some multiple ofk(hence, are divisible byk).Count Potential Subarrays: Every time a remainder repeats, it means there are multiple subarrays (ending at different indices) which have sums divisible by
k. Use the hash map to count these occurrences. For each remainder, if it has been seenntimes before, then there arensubarrays ending at the current index that can be formed which have sums divisible byk.
This approach capitalizes on both the properties of remainders and the utility of hash maps for efficient frequency counts, ensuring that each subarray is checked for divisibility without explicitly computing the sum for every possible subarray, thereby improving efficiency.
Solutions
- C++
- Java
class Solution {
public:
int subarraysWithSumDivisibleByK(vector<int>& array, int divisor) {
int length = array.size();
int currentMod = 0, totalCount = 0;
vector<int> remainderCount(divisor);
remainderCount[0] = 1;
for (int element : array) {
currentMod = (currentMod + element % divisor + divisor) % divisor;
totalCount += remainderCount[currentMod];
remainderCount[currentMod]++;
}
return totalCount;
}
};
The provided C++ code defines a solution for finding the count of subarrays within an integer array where the sum of the elements is divisible by a given divisor K. The function subarraysWithSumDivisibleByK accepts two parameters: a vector array and an integer divisor. It utilizes the properties of modulo operation to efficiently compute the number of such subarrays.
Here's how the function works:
Initialize
lengthto hold the size of the input array.Initialize
currentModto store the current prefix sum modulus andtotalCountto track the total number of valid subarrays.Create a vector
remainderCountof sizedivisorto store the frequency of each modulus value in prefix sums, with an initial count of one for the0modulus to account for sums that are exactly divisible bydivisor.Loop over each element of the array:
- Update
currentModby adding the current element's modulus value, adjusted for negative sums by addingdivisorand taking the modulus again. - Increment
totalCountby the count of previous prefix sums that share the same modulus ascurrentMod, which means their difference is divisible bydivisor. - Increment the count of the current modulus in
remainderCount.
- Update
The function ultimately returns totalCount, which represents the number of subarrays where the sum is divisible by divisor. This approach ensures a comprehensive check through the use of modular arithmetic, optimizing the process to find qualifying subarrays efficiently using a time complexity dependent on the size of the array and the divisor.
class Solution {
public int countSubarraysDivisibleByK(int[] array, int divisor) {
int length = array.length;
int cumulativeModulo = 0, totalCount = 0;
int[] remainderGroups = new int[divisor];
remainderGroups[0] = 1;
for (int value : array) {
cumulativeModulo = (cumulativeModulo + value % divisor + divisor) % divisor;
totalCount += remainderGroups[cumulativeModulo];
remainderGroups[cumulativeModulo]++;
}
return totalCount;
}
}
This Java solution tackles the problem of counting the number of subarrays from a given array where the sum of elements is divisible by a specified value, K. The approach utilizes a cumulative sum and the modulo operation to efficiently compute the result.
Here's a step-by-step explanation of how the solution works:
Initialize
lengthto the size of the input array for easy reference.Declare
cumulativeModuloto store the ongoing sum of array values modulodivisor. Start withtotalCountto count the number of subarrays meeting the criteria.Create an array
remainderGroupsto track how many times each modulo value has occurred so far with a size equal todivisor. Initialize the first element to 1 to account for the subarray consisting of the very first element if it is divisible bydivisor.Iterate through each element in the input array:
- Update
cumulativeModuloby adding the current value modulodivisorand adjust for any negative values to ensure all remainders are positive. - Increase
totalCountby the count of subarrays that have the samecumulativeModulovalue recorded inremainderGroups. This is because if two subarrays have the same remainder when divided bydivisor, the subarray between them has a sum that is divisible bydivisor. - Increment the count for the current
cumulativeModuloinremainderGroups.
- Update
Return the total count of divisible subarrays.
The solution leverages the properties of the modulo operation and prefix sums to elegantly solve a potentially complex problem using a linear time algorithm that is both efficient and easy to understand.