Given an integer array nums and an integer k, return the k most frequent elements within the array.
The test cases are generated such that the answer is always unique.
You may return the output in any order.
Example 1:
Input: nums = [1,2,2,3,3,3], k = 2
Output: [2,3]Example 2:
Input: nums = [7,7], k = 1
Output: [7]Constraints:
1 <= nums.length <= 10^4.-1000 <= nums[i] <= 10001 <= k <= number of distinct elements in nums.
You should aim for a solution with O(n) time and O(n) space, where n is the size of the input array.
A naive solution would be to count the frequency of each number and then sort the array based on each element’s frequency. After that, we would select the top k frequent elements. This would be an O(nlogn) solution. Though this solution is acceptable, can you think of a better way?
Can you think of an algorithm which involves grouping numbers based on their frequency?
Use the bucket sort algorithm to create n buckets, grouping numbers based on their frequencies from 1 to n. Then, pick the top k numbers from the buckets, starting from n down to 1.
To find the k most frequent elements, we first need to know how often each number appears.
Once we count the frequencies, we can sort the unique numbers based on how many times they occur.
After sorting, the numbers with the highest frequencies will naturally appear at the end of the list.
By taking the last k entries, we get the k most frequent elements.
This approach is easy to reason about:
count the frequencies → sort by frequency → take the top k.
[frequency, number] pairs from the map.k elements.class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = {}
for num in nums:
count[num] = 1 + count.get(num, 0)
arr = []
for num, cnt in count.items():
arr.append([cnt, num])
arr.sort()
res = []
while len(res) < k:
res.append(arr.pop()[1])
return resAfter counting how often each number appears, we want to efficiently keep track of only the k most frequent elements.
A min-heap is perfect for this because it always keeps the smallest element at the top.
By pushing (frequency, value) pairs into the heap and removing the smallest whenever the heap grows beyond size k, we ensure that the heap always contains the top k most frequent elements.
In the end, the heap holds exactly the k values with the highest frequencies.
(frequency, number) into the heap.k, pop once to remove the smallest frequency.k most frequent elements.class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = {}
for num in nums:
count[num] = 1 + count.get(num, 0)
heap = []
for num in count.keys():
heapq.heappush(heap, (count[num], num))
if len(heap) > k:
heapq.heappop(heap)
res = []
for i in range(k):
res.append(heapq.heappop(heap)[1])
return resWhere is the length of the array and is the number of top frequent elements.
Each number in the array appears a certain number of times, and the maximum possible frequency is the length of the array.
We can use this idea by creating a list where the index represents a frequency, and at each index we store all numbers that appear exactly that many times.
For example:
freq[1].freq[2].After we build these groups, we look from the highest possible frequency down to the lowest and collect numbers from these groups until we have k of them.
This way, we directly jump to the most frequent numbers without sorting all the elements by frequency.
freq, where freq[i] will store all numbers that appear exactly i times.freq[frequency].1:freq[i], add it to the result list.k numbers, return it.class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = {}
freq = [[] for i in range(len(nums) + 1)]
for num in nums:
count[num] = 1 + count.get(num, 0)
for num, cnt in count.items():
freq[cnt].append(num)
res = []
for i in range(len(freq) - 1, 0, -1):
for num in freq[i]:
res.append(num)
if len(res) == k:
return res