You are given an integer array nums
and an integer k
. Your task is to find and return the k
most frequent elements in the array. The order of the returned elements does not matter.
Example 1:
nums = [1,1,1,2,2,3], k = 2
[1,2]
(or [2,1]
, the order doesn't matter)
Example 2:
nums = [1], k = 1
[1]
k=1
, we return it.Constraints:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
k
is always valid, meaning 1 <= k <=
(number of unique elements in the array).Follow-up: Can you design an algorithm with a time complexity better than O(n log n), where n is the size of the input array?
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 goal is to find the most frequently occurring items from a larger set. The brute force way means we count each item one by one, comparing against every other item. Then we sort them based on how often they appeared and pick the top ones.
Here's how the algorithm would work step-by-step:
def top_k_frequent_elements_brute_force(numbers, k_most_frequent):
element_counts = []
unique_numbers = []
# Iterate through the input to determine unique elements
for number in numbers:
if number not in unique_numbers:
unique_numbers.append(number)
# Count frequency of each unique element
for unique_number in unique_numbers:
frequency = 0
# Iterate through the list to determine count
for number in numbers:
if number == unique_number:
frequency += 1
element_counts.append((unique_number, frequency))
# Sort element counts based on frequency
element_counts.sort(key=lambda item: item[1], reverse=True)
# Return the top 'k' frequent elements
top_k_elements = []
# Limit based on k value
for i in range(min(k_most_frequent, len(element_counts))):
top_k_elements.append(element_counts[i][0])
return top_k_elements
To find the most frequent items, we want to count how many times each one appears and then pick the top few. We use a system to sort items by their count, letting us quickly grab the most frequent ones without checking every item repeatedly.
Here's how the algorithm would work step-by-step:
def top_k_frequent(numbers, k_most_frequent):
element_counts = {}
for number in numbers:
element_counts[number] = element_counts.get(number, 0) + 1
# Bucket sort based on frequency, handling edge cases.
frequency_buckets = [[] for _ in range(len(numbers) + 1)]
for number, count in element_counts.items():
frequency_buckets[count].append(number)
top_k_elements = []
# Iterate backwards to get most frequent elements first.
for count in range(len(numbers), 0, -1):
for number in frequency_buckets[count]:
top_k_elements.append(number)
# Stop once we have the k most frequent elements.
if len(top_k_elements) == k_most_frequent:
return top_k_elements
return top_k_elements
Case | How to Handle |
---|---|
Empty input array | Return an empty list immediately as there are no elements to count frequencies for. |
k is zero | Return an empty list since we want to find zero most frequent elements. |
k is larger than the number of unique elements | Return all unique elements, as that's the maximum number of frequent elements available. |
Array contains only one unique element | Return the array containing only that element if k>=1, otherwise return empty array if k=0. |
All elements in the array are the same | Return the element within a list of size 1 if k>=1, otherwise return empty array if k=0. |
Large input array exceeding memory limits for frequency map | Consider using external memory or approximate frequency counting algorithms if memory is a constraint. |
Negative numbers present in the array | The solution should handle negative numbers correctly since hash map can store negative numbers as keys. |
Extreme boundary integer values in the array (e.g., Integer.MAX_VALUE, Integer.MIN_VALUE) | The solution must handle extreme values without causing integer overflow issues in the frequency counting or comparison steps. |