Problem of The Day: Count Subarrays Where Max Element Appears at Least K Times
Problem Statement
Intuition
We need to find the number of subarrays where the maximum element appears exactly k times.
Since the maximum value of the entire array is fixed, we can track how many times it appears within a sliding window to efficiently find valid subarrays.
Approach
- First, calculate the maximum value
max_valin the array. - Use two pointers (
startandend) to form a sliding window:- Move
endforward through the array. - Whenever
nums[end] == max_val, increasecount.
- Move
- When
count == k, it means the current window[start, end]contains exactlykoccurrences ofmax_val.- Important: Once we have a valid window, any subarray that starts at
startor later and ends atend(or later) will still have exactlykmax_valvalues (becauseendis fixed at the moment). - Since
endcan be extended toN-1without changing the count, the number of valid subarrays is(N - end).
- Important: Once we have a valid window, any subarray that starts at
- After counting, shrink the window from the left by moving
start, and decreasecountifnums[start] == max_val.
Why (N - end)?
When we find a valid window where the number of max_val is exactly k, the subarrays:
[start, end][start+1, end][start+2, end]- …
- and so on, up to the end of the array
will all be valid without changing the number of
max_val.
Thus, there are(N - end)valid subarrays for the currentstart.
Complexity
-
Time complexity:
\(O(n)\)
Bothstartandendpointers move from left to right across the array, each visiting each element at most once. -
Space complexity:
\(O(1)\)
We only use a few extra integer variables.
Code
class Solution:
def countSubarrays(self, nums: List[int], k: int) -> int:
res = 0
start = 0
N = len(nums)
count = 0
max_val = max(nums)
for end in range(N):
count += 1 if nums[end] == max_val else 0
while count == k and start <= end:
res += (N - end)
count -= 1 if nums[start] == max_val else 0
start += 1
return res
Editorial
Approach 1: Sliding Window
class Solution:
def countSubarrays(self, nums: List[int], k: int) -> int:
max_element = max(nums)
ans = start = max_elements_in_window = 0
for end in range(len(nums)):
if nums[end] == max_element:
max_elements_in_window += 1
while max_elements_in_window == k:
if nums[start] == max_element:
max_elements_in_window -= 1
start += 1
ans += start
return ans