You are given an integer array nums
and a positive integer k
.
Return the number of subarrays where the maximum element of nums
appears at least k
times in that subarray.
A subarray is a contiguous sequence of elements within an array.
For example:
nums = [1, 3, 2, 3, 3], k = 2
Output: 6
Explanation: The subarrays that contain the element 3 at least 2 times are: [1,3,2,3]
, [1,3,2,3,3]
, [3,2,3]
, [3,2,3,3]
, [2,3,3]
and [3,3]
.
Another example:
nums = [1, 4, 2, 1], k = 3
Output: 0
Explanation: No subarray contains the element 4 at least 3 times.
Constraints:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6
1 <= k <= 10^5
Write a function to solve this problem efficiently.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The basic idea is to look at every possible chunk of numbers within the entire sequence. For each of these chunks, we'll count how many times the biggest number in the entire sequence appears within that chunk.
Here's how the algorithm would work step-by-step:
def count_subarrays_where_max_element_appears_at_least_k_times(
sequence_of_numbers, required_number_of_times
): number_of_valid_subarrays = 0
sequence_length = len(sequence_of_numbers)
# Find the maximum element in the entire sequence
maximum_element_in_sequence = max(sequence_of_numbers)
for start_index in range(sequence_length):
for end_index in range(start_index, sequence_length):
current_subarray =
sequence_of_numbers[start_index : end_index + 1]
# Count occurrences of max element in the current subarray
maximum_element_count = 0
for element in current_subarray:
if element == maximum_element_in_sequence:
maximum_element_count += 1
# Check if max element appears at least k times
if (
maximum_element_count >= required_number_of_times
):
number_of_valid_subarrays += 1
return number_of_valid_subarrays
The goal is to efficiently count valid segments in a list. The key is to avoid recounting segments by reusing information about previously counted segments and focusing on segments that become valid as we move through the list.
Here's how the algorithm would work step-by-step:
def count_subarrays(number_list, min_occurrences):
list_length = len(number_list)
if list_length == 0:
return 0
maximum_number = max(number_list)
subarray_count = 0
window_start = 0
max_number_count = 0
for window_end in range(list_length):
if number_list[window_end] == maximum_number:
max_number_count += 1
# Shrink window from left if necessary
while max_number_count >= min_occurrences:
# Add valid subarrays ending at window_end
subarray_count += list_length - window_end
if number_list[window_start] == maximum_number:
max_number_count -= 1
window_start += 1
return subarray_count
Case | How to Handle |
---|---|
Empty input array | Return 0 since no subarrays are possible. |
k is zero or negative | If k is zero return the number of all possible subarrays; if negative treat as zero. |
Array with one element | Check if k is 1 and if the element is the max (which it is) and return 1, else return 0. |
Array with all identical elements | If k is less than or equal to length of the subarray (which is the same element's count), the subarray is valid; count total valid subarrays. |
Array with negative numbers | The algorithm should correctly find the maximum element and its frequency regardless of negative values. |
Large array and large k values potentially exceeding integer limits in counting | Use long or appropriate data type to store the count of valid subarrays and maximum element frequencies to prevent overflow. |
k is greater than the length of the input array | No subarray can satisfy the condition; return 0. |
Array contains Integer.MAX_VALUE or Integer.MIN_VALUE | Compare elements carefully to correctly identify the maximum even with extreme values. |