
Problem Statement
In this problem, we're provided with an integer array nums
and an integer k
. The objective is to identify the longest contiguous subarray of nums
such that the frequency of each element within that subarray does not exceed k
, where the frequency is defined as the number of occurrences of an element within the array. We need to return the length of this longest "good" subarray. A subarray is a contiguous part of the original array and all elements must satisfy the frequency condition to qualify as "good".
Examples
Example 1
Input:
nums = [1,2,3,1,2,3,1,2], k = 2
Output:
6
Explanation:
The longest possible good subarray is [1,2,3,1,2,3] since the values 1, 2, and 3 occur at most twice in this subarray. Note that the subarrays [2,3,1,2,3,1] and [3,1,2,3,1,2] are also good. It can be shown that there are no good subarrays with length more than 6.
Example 2
Input:
nums = [1,2,1,2,1,2,1,2], k = 1
Output:
2
Explanation:
The longest possible good subarray is [1,2] since the values 1 and 2 occur at most once in this subarray. Note that the subarray [2,1] is also good. It can be shown that there are no good subarrays with length more than 2.
Example 3
Input:
nums = [5,5,5,5,5,5,5], k = 4
Output:
4
Explanation:
The longest possible good subarray is [5,5,5,5] since the value 5 occurs 4 times in this subarray. It can be shown that there are no good subarrays with length more than 4.
Constraints
1 <= nums.length <= 105
1 <= nums[i] <= 109
1 <= k <= nums.length
Approach and Intuition
To solve this problem efficiently, the concept of a sliding window combined with a frequency map can be effectively applied. Here's a step-by-step plan:
- Initialize two pointers to represent the current window of the array. These are usually termed as the
start
andend
pointers. - Use a hashmap (or dictionary) to keep track of the frequency of each element within the current window.
- Expand the
end
pointer to include elements in the window until the condition is violated (i.e., the frequency of some element in the window exceedsk
). - Once the condition is violated, start moving the
start
pointer to the right to reduce the size of the window until the subarray becomes "good" again (i.e., the frequency of all elements are within the limit set byk
). - The size of the window at each valid state (where all frequencies are ≤ k) can be considered as a potential answer. Always update and record the maximum size obtained.
- Continue this until the
end
pointer has traversed the entire array.
- Example walkthrough with
nums = [1,2,3,1,2,3,1,2], k = 2
:- Increase the window size by moving
end
until you exceedk
with any number. - Initially, the window grows to encompass
1,2,3,1,2,3
before any frequency exceedsk
. - At this point, the largest good window has a length of 6.
- Adjust
start
andend
trying to find a potentially larger good subarray, but none can be found in this instance.
- Increase the window size by moving
This approach ensures that each element is processed a limited number of times, making the sliding window technique efficient for this problem. The use of the frequency hashmap enables quick checks and updates for the conditions described.
Solutions
- C++
- Java
- Python
class Solution {
public:
int longestUniformSubarray(vector<int>& elements, int threshold) {
int len = elements.size();
unordered_map<int, int> countMap;
int left = 0;
int excessCount = 0;
for (int right = 0; right < len; right++) {
countMap[elements[right]]++;
if (countMap[elements[right]] == threshold + 1) {
excessCount++;
}
if (excessCount > 0) {
countMap[elements[left]]--;
if (countMap[elements[left]] == threshold) {
excessCount--;
}
left++;
}
}
return len - left;
}
};
You're aiming to compute the length of the longest subarray wherein each element appears at most k
times within the array. By establishing a window of potential valid subarrays through incrementally adjusting the left and right pointers, the solution makes efficient use of space and runs competitively fast. Here's how the code in C++ manages this:
- Maintain a hashmap to keep track of the frequency of each element over the current window defined by
left
andright
pointers. - Incrementally explore the array using the
right
pointer. As each element frequency increases, update the count in this map. - When any element exceeds the allowed threshold frequency (
k
), it is marked as exceeding by using anexcessCount
. - Use the
left
pointer to shrink the window from the left, decrementing the count of the element atleft
in the map, until theexcessCount
becomes zero again—indicating all elements within the window do not exceed the threshold. - The size of the window at the end of this process (when
right
reaches the end of the array) shows the largest such window encountered that satisfies the condition.
This approach primarily focuses on managing and adjusting the window of "valid" subarrays until the optimal solution (longest valid subarray) is found while updating the frequency map accordingly. It strikes a good balance between time complexity (efficient traversal) and space complexity (minimal space usage beyond the original array size).
class Solution {
public int maxLengthSubarray(int[] array, int target) {
int size = array.length;
Map<Integer, Integer> countMap = new HashMap();
int begin = 0;
int excessElements = 0;
for (int end = 0; end < size; end++) {
countMap.put(array[end], countMap.getOrDefault(array[end], 0) + 1);
if (countMap.get(array[end]) == target + 1) {
excessElements++;
}
if (excessElements > 0) {
countMap.put(array[begin], countMap.get(array[begin]) - 1);
if (countMap.get(array[begin]) == target) {
excessElements--;
}
begin++;
}
}
return size - begin;
}
}
The provided Java solution is designed to find the length of the longest subarray where the frequency of each element does not exceed a specified value, target
. The approach uses a sliding window technique along with a hashmap to efficiently track the frequency of each element in the current window. Here's a concise summary of how the solution is implemented:
- Initialize a hashmap
countMap
to store the frequency of elements within the current window. - Use two pointers,
begin
andend
, to represent the current window's start and end positions respectively. - Iterate through the array using the
end
pointer. For each element at positionend
, update its frequency incountMap
. - Check if the updated frequency exceeds
target
by one (i.e.,target + 1
). If so, increment a counterexcessElements
that tracks the number of elements whose frequency is beyond the allowed count. - If
excessElements
is greater than zero, it's necessary to shrink the window from the beginning by moving thebegin
pointer right. During this, decrease the frequency of the element at thebegin
position, and if its frequency drops back totarget
, decrementexcessElements
. - Continue expanding and contracting the window until
end
reaches the end of the array. - Finally, return the maximum length of the subarray that meets the condition, which is calculated using the difference between the size of the array and the position of
begin
.
This method ensures that the subarray found is the longest possible where no element appears more than target
times, achieved through an optimal O(n) complexity where n is the size of the array.
class Solution:
def longestSubarrayLength(self, values: List[int], threshold: int) -> int:
length = len(values)
count_map = Counter()
begin = 0
count_exceed_threshold = 0
for finish in range(length):
count_map[values[finish]] += 1
if count_map[values[finish]] == threshold + 1:
count_exceed_threshold += 1
if count_exceed_threshold:
count_map[values[begin]] -= 1
if count_map[values[begin]] == threshold:
count_exceed_threshold -= 1
begin += 1
return length - begin
This Python 3 solution addresses the problem of finding the length of the longest subarray in which the frequency of any element does not exceed a specified threshold, k
. The function longestSubarrayLength
accepts two parameters: values
, a list of integers, and threshold
, an integer representing the maximum allowable frequency for any element within the subarray.
Let's break down the solution:
- Initialize a length variable
length
to the length of thevalues
list. - Create a
count_map
to keep track of the frequency of elements. - Set
begin
, a pointer to the start of the window, to zero andcount_exceed_threshold
, a counter for when an element's frequency exceeds the threshold, to zero. - Use a loop to traverse through the
values
list and increment the frequency of each element incount_map
. - If the frequency of the currently processed element exceeds
threshold
, incrementcount_exceed_threshold
. - If any frequency exceeds the set
threshold
, decrease the frequency of the element at thebegin
position and possibly adjustcount_exceed_threshold
if the frequency goes back down to the threshold. Then incrementbegin
to narrow the window. - The desired length of the longest subarray is found by calculating
length - begin
at the end of the loop.
This approach efficiently finds the solution using a sliding window technique to adjust the size of the potential subarray based on the frequency conditions provided.
No comments yet.