
Problem Statement
The task is to find the number of "good subarrays" within an integer array nums, given an integer k. A subarray is regarded as "good" when it contains exactly k distinct integers. It is important to understand that a subarray must be a contiguous segment of the parent array nums. The distinction between any two subarrays will depend on their content diversity relative to k, making the approach to this problem non-trivial especially as k and the size of nums increase.
Examples
Example 1
Input:
nums = [1,2,1,2,3], k = 2
Output:
7
Explanation:
Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2]
Example 2
Input:
nums = [1,2,1,3,4], k = 3
Output:
3
Explanation:
Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].
Constraints
1 <= nums.length <= 2 * 1041 <= nums[i], k <= nums.length
Approach and Intuition
Given the problem's requirement to count subarrays with exactly k distinct integers, one can anticipate several foundational steps and intuitions:
Direct Counting is Infeasible: With the array length potentially reaching up to 20,000, exhaustive enumeration and verification of all possible subarrays will result in a super-polynomial time complexity, which is computationally infeasible.
Sliding Window Technique: A viable approach to solve this problem optimally is to use a sliding window method combined with a hash map. This technique helps dynamically track the count of distinct integers as the window expands or contracts.
Handling Distinct Counts: Every extension or contraction of the window can be handled efficiently by updating the hash map, which tracks the count of each number inside the current window:
- When a new number is added to the window (i.e., expanding), increase its count in the map.
- When a number is removed (i.e., window is contracting), reduce its count, potentially removing it from the map if its count drops to zero.
Double Counting via Sliding Window Adjustment: The challenge intensifies with needing to ensure that each subarray has exactly
kdistinct numbers. One approach is to calculate subarrays with at mostkdistinct integers and subtract the count of subarrays with at mostk-1distinct integers from it.Efficiency Concerns: Since every operation inside the window (adding or removing an element) can be achieved in constant time due to the hash map, the sliding window technique remains efficient. The overall time complexity, in the ideal case, is linear relative to the size of
numsmultiplied by the operations performed per element (updating the map).
By applying these strategies, one can accurately and efficiently determine the number of good subarrays for given constraints, optimizing both performance and correctness.
Solutions
- C++
class Solution {
public:
int countKDistinctSubarrays(vector<int>& arr, int k) {
vector<int> count(arr.size() + 1, 0);
int totalSubarrays = 0, start = 0, end = 0, windowSize = 0;
while (end < arr.size()) {
if (++count[arr[end++]] == 1) {
k--;
}
if (k < 0) {
--count[arr[start++]];
k++;
windowSize = 0;
}
if (k == 0) {
while (count[arr[start]] > 1) {
--count[arr[start++]];
windowSize++;
}
totalSubarrays += (windowSize + 1);
}
}
return totalSubarrays;
}
};
In the provided C++ code, the solution focuses on finding the number of subarrays within a given array that contain exactly k distinct integers. It uses a sliding window approach with two pointers, start and end, to efficiently determine the count of such subarrays without the need to check every possible subarray explicitly. Here's a breakdown of how the code tackles the problem:
- A function
countKDistinctSubarraysis declared, which takes a vector of integersarrand an integerkas parameters, representing the array and the number of distinct integers in the subarrays, respectively. - Initially, a count vector is created to keep track of the frequency of each element in the current window. The
totalSubarraysvariable is initialized to zero to store the result. - The outer
whileloop progresses theendpointer from the beginning to the end of the array, incrementing the count of each element as it is included in the window. If a new distinct element is added (count[arr[end]] == 1),kis decremented. - When
kbecomes negative (meaning the window has more thankdistinct integers), the window is adjusted by moving thestartpointer forward and reducing the counts accordingly untilkis non-negative. - An inner
whileloop further adjusts thestartpointer to ensure that every possible subarray starting from the current position ofstartand ending atend - 1is counted. The count of such valid subarrays is then incremented based on the size of the window freeze frame, which ensures subarrays containing exactlykdistinct integers are counted. - Finally, the function returns
totalSubarrays, which is the count of subarrays containing exactlykdistinct integers.
The beauty of this approach lies in its efficiency—by maintaining a dynamic sliding window of the array, the solution avoids the computational overhead of checking each subarray individually, which would be substantially slower especially for large arrays. The sliding window technique, combined with careful counting of distinct elements and adjusting the window size, offers an optimal solution to the problem.
- Java
class Solution {
public int countSubarraysWithKDistinct(int[] arr, int k) {
int[] countMap = new int[arr.length + 1];
int total = 0;
int start = 0;
int end = 0;
int count = 0;
while (end < arr.length) {
if (countMap[arr[end++]]++ == 0) {
k--;
}
if (k < 0) {
--countMap[arr[start++]];
k++;
count = 0;
}
if (k == 0) {
while (countMap[arr[start]] > 1) {
--countMap[arr[start++]];
count++;
}
total += (count + 1);
}
}
return total;
}
}
This solution aims to tackle the problem of counting subarrays in an array that contain exactly K different integers. It uses an array-based sliding window approach to efficiently keep track of the number of distinct integers and calculates the subarray counts.
- The function
countSubarraysWithKDistincttakes two parameters: an integer arrayarrand an integerkrepresenting the desired number of distinct integers. - A
countMaparray is utilized to store the frequency of each integer in the current window of the array. - Variables
total,start,end, andcountare initialized to manage the counting and the window's bounds during the traversal of the array. - As the
endpoint of the sliding window expands (end++), the array element at this position increments in thecountMapand checks if a new integer has been added (countMap[arr[end]]++ == 0). If yes, decrementk. - If
kbecomes less than zero, meaning the window has more thankdistinct integers, the algorithm shrinks the window from thestartside untilkis no longer negative. This is done by incrementing thestartpointer and adjusting the map andkaccordingly. - When
kis exactly zero, indicating the window has exactlykdistinct integers, count possible subarrays originating from this window configuration. It incrementscountfor all duplicate start elements and adds these tototal. - The algorithm keeps adjusting the window using the
startandendpointers and updates thetotalcount of valid subarrays. - Finally,
totalis returned, providing the count of all subarrays inarrthat contain exactlykdifferent integers.
This Java implementation efficiently manages the exploration of subarrays using both increasing and decreasing the bounds of a sliding window based on the status of k and updates the count of distinct integers efficiently using an array to represent current integer frequencies within the window.
- Python
class Solution:
def countDistinctSubarrays(self, arr: List[int], distinct_num: int) -> int:
count_dict = [0] * (len(arr) + 1)
total_subarrays = 0
window_start = 0
window_end = 0
active_count = 0
while window_end < len(arr):
count_dict[arr[window_end]] += 1
if count_dict[arr[window_end]] == 1:
distinct_num -= 1
if distinct_num < 0:
count_dict[arr[window_start]] -= 1
if count_dict[arr[window_start]] == 0:
distinct_num += 1
window_start += 1
active_count = 0
if distinct_num == 0:
while count_dict[arr[window_start]] > 1:
count_dict[arr[window_start]] -= 1
window_start += 1
active_count += 1
total_subarrays += (active_count + 1)
window_end += 1
return total_subarrays
This Python3 solution defines a method countDistinctSubarrays in the Solution class to solve the problem of finding subarrays containing exactly K distinct integers. Here's how the implementation works:
- Initialize a list
count_dictof sizelen(arr) + 1to zero, to keep track of the count of each element within the current window of the subarray. - Set
total_subarrays,window_start,window_end, andactive_countto 0. - Traverse the array using the
window_endvariable. For each element atwindow_end, increment its count incount_dict. - Decrement
distinct_numwhen a new distinct element is encountered by checking if its count becomes one. - If
distinct_numbecomes negative, adjust thewindow_startto potentially remove some elements from the current subarray to try and bring back the count of distinct integers within the required limit. - Whenever
distinct_numreaches zero, meaning the subarray betweenwindow_startandwindow_endhas exactly K distinct integers, further adjustwindow_startand count the number of valid subarrays. - Continue this until
window_endhas traversed the entire array. - Return the
total_subarrayscount, which represents the number of subarrays having exactly K distinct integers.
This approach utilises the sliding window technique combined with a frequency count array, effectively allowing the program to consider each possible subarray and record the valid ones as per the given conditions. Adjustments of the window_start help ensure that once a valid subarray configuration is disturbed (due to an exceeding number of distinct integers), it is realigned to remain within the problem constraints.
Efficient management of the subarray window and an accurate count of valid configurations ensure that the solution is both effective and optimal for large inputs.