Efficiently Count Complete Subarrays

Count Complete Subarrays — Match Distinct Count in Subarrays

Problem Statement

You’re given an array of positive integers nums.

A complete subarray is defined as a subarray that contains all the distinct elements present in the entire array.

Your task is to count the number of complete subarrays in nums.

Explanation:

The total number of distinct elements in the array is 3: {1, 2, 3}.

Now, let’s find all subarrays that also contain all 3:

  • [1,3,1,2]

  • [1,3,1,2,2]

  • [3,1,2]

  • [3,1,2,2]

So, there are 4 complete subarrays.

Best Technique – Sliding Window + At-Most K Trick

This problem might seem like just a subarray count, but it tests your ability to:

  • Recognize a fixed-size condition inside variable-sized subarrays

  • Use a hash map or frequency counter for distinct element tracking

  • Leverage the at-most-k sliding window pattern

Let’s explore multiple ways to solve this—from brute force to optimal—and see what each one teaches us.

Different Approaches:

Approach 1: Brute Force with Set Tracking

Try every possible subarray, use a Set to count how many distinct elements it contains. If it matches the total count in the full array—count it.


public static int countCompleteSubarrays(int[] nums) { int totalDistinct = countDistinct(nums); int n = nums.length; int result = 0; for (int i = 0; i < n; i++) { Set<Integer> seen = new HashSet<>(); for (int j = i; j < n; j++) { seen.add(nums[j]); if (seen.size() == totalDistinct) { result++; } } } return result; } private static int countDistinct(int[] nums) { Set<Integer> set = new HashSet<>(); for (int num : nums) set.add(num); return set.size(); }

Approach 2: HashMap for Frequency Counting (Improved Brute Force)

Use a HashMap to reduce redundancy and speed up lookups. You still check every subarray, but with frequency tracking, allowing for early cut-offs.

public static int countCompleteSubarraysHashMap(int[] nums) { int totalDistinct = countDistinct(nums); int result = 0; for (int i = 0; i < nums.length; i++) { Map<Integer, Integer> freq = new HashMap<>(); for (int j = i; j < nums.length; j++) { freq.put(nums[j], freq.getOrDefault(nums[j], 0) + 1); if (freq.size() == totalDistinct) { result++; } } } return result; }

Approach 3: Optimized using At-Most-K Sliding Window

exactlyK = atMost(K) - atMost(K - 1)

We count subarrays with exactly the required number of distinct elements.

public static int countCompleteSubarraysOptimized(int[] nums) { int totalDistinct = countDistinct(nums); return atMost(nums, totalDistinct) - atMost(nums, totalDistinct - 1); } private static int atMost(int[] nums, int k) { Map<Integer, Integer> freq = new HashMap<>(); int left = 0, result = 0; for (int right = 0; right < nums.length; right++) { freq.put(nums[right], freq.getOrDefault(nums[right], 0) + 1); while (freq.size() > k) { freq.put(nums[left], freq.get(nums[left]) - 1); if (freq.get(nums[left]) == 0) freq.remove(nums[left]); left++; } result += right - left + 1; } return result; }

⚠️ Common Pitfalls

  • Not using a sliding window properly when calculating atMost(k)

  • Forgetting to count from index i to j in subarrays

  • Trying to use Set to count exact matches without optimizing

  • Not recognizing that subtracting atMost(k-1) from atMost(k) gives exact count

📊 Time and Space Complexity

ApproachTime Complexity      Space Complexity
Brute Force      O(n²)           O(n)
HashMap Traversal      O(n²)           O(n)
Optimized Sliding Window      O(n)           O(n)

🌍 Real-World Applications

  • Analyzing user activity in web applications (e.g., checking if all types of actions are performed in a time window)

  • Data completeness in scientific computing (ensuring that all conditions or data points are included in a dataset)

  • Classification tasks where every distinct element needs to be accounted for.


I hope you found this article insightful! Keep exploring, keep learning, and don’t forget to check back daily for more exciting problem breakdowns. If you know someone who would benefit from this, share it with them and help them grow too! That’s it for today—see you in the next post!

                                                                                                                                         Signing off!! 

                                                                                                Master DSA One Problem at a Time :)

Comments

Popular posts from this blog

Trailing Zeros in Factorial – How Many and Why?

Divisible Drama — Who’s In, Who’s Out?

Zero Array After Queries