2958. Length of Longest Subarray With at Most K Frequency
MediumView on LeetCode
Problem Overview
A subarray is good when every value appears at most k times.
Intuition
A subarray is good when every value appears at most k times. As you grow a window, the only way it becomes bad is that the newly added value exceeds k - every other count was already legal. Shrink from the left until that value is back to k. Every window [l, r] you keep is good, so track the maximum length.
Algorithm
- 1Keep a frequency map for the current window [l, r] and ans = 0.
- 2For each right endpoint r: increment freq[nums[r]].
- 3While freq[nums[r]] > k: decrement freq[nums[l]] and advance l.
- 4Update ans with r - l + 1 (the current valid window length).
- 5Return ans. Leaving zero counts in the map is fine - unused keys do not affect correctness.
Example Walkthrough
Input: nums = [1, 2, 3, 1, 2, 3, 1, 2], k = 2
- 1.Grow to [1,2,3,1,2,3] - each of 1, 2, 3 appears twice; length 6.
- 2.Add the next 1 -> count(1) = 3 > 2. Shrink from the left until count(1) <= 2.
- 3.No later window is longer than 6, so the answer is 6.
Output: 6
Common Pitfalls
- •You only need to shrink while the newly added value exceeds k - other values cannot suddenly break the limit.
- •n can be 1e5, so O(n^2) nested scans will TLE; each index moves at most once.
- •k can equal n; then the whole array is always good.
- •Do not confuse "at most k frequency per value" with "at most k distinct values".
2958.cs
C#
// Approach: Sliding window. Expand r; track frequencies. When nums[r] appears
// more than k times, advance l until that count is <= k. Window length r-l+1
// is always valid; track the maximum. Skip removing zeroed keys - unused
// entries are harmless and saves dictionary churn.
// Complexity: O(n) time and O(min(n, U)) space (U = distinct values in the window).
public class Solution
{
public int MaxSubarrayLength(int[] nums, int k)
{
var freq = new Dictionary<int, int>();
int l = 0, ans = 0;
for (int r = 0; r < nums.Length; r++)
{
freq.TryGetValue(nums[r], out int count);
freq[nums[r]] = count + 1;
while (freq[nums[r]] > k)
{
freq[nums[l]]--;
l++;
}
ans = Math.Max(ans, r - l + 1);
}
return ans;
}
}
Was this solution helpful?