Core Java

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 at i using a dynamic programming array dpSum[].
  • If the arithmetic mean (i.e., sum / length_of_subarray) equals S, 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:

java count subarrays average value example 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.

Download
You can download the full source code of this example here: java count subarrays specified average value

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button