Count Subarrays with a Specified Average Value
This article will tackle a problem involving subarrays and arithmetic means, aiming to develop an efficient solution. So, lets explore how to efficiently count subarrays with a specified average value in Java. The problem is defined as follows:
1. Problem Statement
Given an array X and an integer S, find how many contiguous subarrays of X have an arithmetic mean equal to S. For instance, given X = [5, 3, 6, 2] and S = 4, the result is 3. The subarrays [5, 3], [6, 2], and [5, 3, 6, 2] all have an arithmetic mean of 4.
The array X can have up to 100,000 elements, and each element in X is an integer within the range [-1,000,000,000, +1,000,000,000]. Similarly, the target S can also be a large integer. Therefore, efficiency is crucial.
2. Brute Force Approach
We can start with a brute-force solution, which works by iterating over all possible subarrays and calculating their arithmetic mean. This solution works for small datasets but becomes inefficient for larger arrays.
public class BruteForceMeanSubarrays {
public static int returnSubsequenceCount(int[] X, int S) {
int counter = 0;
for (int i = 0; i < X.length; i++) {
int[] dpSum = new int[X.length]; // Dynamic programming array to store the sum of subarrays
dpSum[i] = X[i]; // Initialize with the current element
if (X[i] == S) { // Check if the current element is equal to the target mean
counter++;
}
for (int j = i + 1; j < X.length; j++) {
int sum = dpSum[j - 1] + X[j]; // Calculate sum of subarray from i to j
dpSum[j] = sum; // Store the subarray sum
// Check if the mean of the subarray equals S
if ((double) sum / (j - i + 1) == S) {
counter++;
}
}
}
return counter;
}
public static void main(String[] args) {
int[] X = {5, 3, 6, 2};
int S = 4;
int result = returnSubsequenceCount(X, S);
System.out.println("Number of subarrays with mean " + S + ": " + result);
}
}
Here is how it works:
- We initialize a counter to keep track of valid subarrays.
- For every starting index
i, we calculate the sum of all subarrays starting atiusing a dynamic programming arraydpSum[]. - If the arithmetic mean (i.e.,
sum / length_of_subarray) equalsS, we increment the counter.
Output:
Number of subarrays with mean 4: 3
2.1 Limitations
While this solution works for small arrays, its time complexity is O(n²) because we calculate sums for every subarray starting from every index. This becomes inefficient when n (length of the array) reaches up to 100,000.
3. Optimized Approach
The brute-force approach is simple but becomes inefficient with large datasets. With a time complexity of O(n²), the algorithm slows down significantly as the array size increases. For arrays with up to 100,000 elements, we need a more efficient solution to handle the computation within a reasonable time.
To do this, we can use the idea of prefix sums, reducing the time complexity to O(n). This optimized approach makes use of a hash map to track the number of times each prefix sum appears, allowing us to count valid subarrays efficiently.
public class OptimizedArithmeticMeanSubarrays {
public static int countSubarraysWithMean(int[] X, int S) {
Map<Long, Integer> prefixSumCount = new HashMap<>();
long sum = 0; // Running sum of the array elements
int count = 0;
// Base case: A prefix sum of 0 occurs once (to account for subarrays starting from index 0)
prefixSumCount.put(0L, 1);
for (int i = 0; i < X.length; i++) {
sum += X[i]; // Update the running sum
// Calculate the required sum for the subarray's arithmetic mean to equal S
long requiredSum = sum - (long) S * (i + 1);
// If the required sum exists in the prefix map, count the valid subarrays
if (prefixSumCount.containsKey(requiredSum)) {
count += prefixSumCount.get(requiredSum);
}
// Update the prefix sum map
prefixSumCount.put(sum - (long) S * (i + 1), prefixSumCount.getOrDefault(sum - (long) S * (i + 1), 0) + 1);
}
return count;
}
public static void main(String[] args) {
int[] X = {5, 3, 6, 2};
int S = 4;
int result = countSubarraysWithMean(X, S);
System.out.println("Number of subarrays with mean " + S + ": " + result);
}
}
The countSubarraysWithMean method takes an integer array X and an integer S as parameters, initializing a hash map, prefixSumCount, to store adjusted prefix sums for efficient counting of valid subarrays. A long variable sum tracks the running total, while an integer variable count records valid subarrays, starting with an entry of 0 mapped to 1. As the method iterates through X, it updates the running sum, calculates the requiredSum by subtracting S * (i + 1), checks if requiredSum exists in the map to update the count, and adds the adjusted prefix sum to the hash map.
Output:
4. Conclusion
In this article, we looked at how to count contiguous subarrays with a specific arithmetic mean. We started with a simple but slow method and then presented a faster approach using prefix sums and a hash map. This optimized method helps efficiently find valid subarrays, even in large datasets, offering a clear solution to the problem.
5. Download the Source Code
This article covers how to count subarrays with a specified average value in Java.
You can download the full source code of this example here: java count subarrays specified average value


