2958. Length of Longest Subarray With at Most K Frequency

  • Array
  • Hash Table
  • Sliding Window
TIME
O(n)
SPACE
O(n)
problem on leetcode ↗source on github ↗

Intuition

The "good" property is monotone under shrinking: if a window satisfies "every frequency <= k", so does any sub-window of it. That's exactly the condition for a two-pointer sliding window, grow the right end greedily, and whenever the window breaks the rule, shrink from the left until it holds again.

Only one element can ever break the rule at a time: the one just added. So the shrink loop just needs to bring that element's count back down to k.

Approach

  1. Keep a hash map freq of counts inside the current window, and a left pointer left.
  2. For each right index r:
    • Increment freq[nums[r]].
    • While freq[nums[r]] > k, decrement freq[nums[left]] and advance left.
    • Update the answer with r - left + 1.
  3. Return the largest window seen.

Each index enters and leaves the window at most once, so the total work is linear.

Complexity

  • Time: O(n), amortized; left only moves forward
  • Space: O(n), the frequency map

Edge Cases

  • All identical values (Example 3) → answer is exactly k
  • k >= n → the whole array is good → answer n
  • k = 1 → longest run of pairwise-distinct values
  • Values up to 10^9 → use a hash map, not a fixed array
  • The answer is always at least 1 since k >= 1

Code

from typing import List
from collections import defaultdict


class Solution:
    def maxSubarrayLength(self, nums: List[int], k: int) -> int:
        """
        2958. Length of Longest Subarray With at Most K Frequency
        Time: O(n)
        Space: O(n)
        """
        freq = defaultdict(int)
        left = 0
        best = 0

        for r, x in enumerate(nums):
            freq[x] += 1
            # only the just-added value can violate the limit
            while freq[x] > k:
                freq[nums[left]] -= 1
                left += 1
            best = max(best, r - left + 1)

        return best