We have an array of integers that may contain duplicates, and we need to find which elements appear most often. We want the top k by frequency. The order of the output doesn't matter, which gives flexibility in how we collect results.
There are two steps: counting how often each element appears, then selecting the k elements with the highest counts. Counting is straightforward with a hash map. The second step is where the approaches differ, because how we select the top k determines whether the solution is O(n log n), O(n log k), or O(n).
1 <= nums.length <= 10^5 → With n up to 100,000, O(n log n) passes, but the follow-up asks us to beat it. This points toward O(n log k) or O(n) solutions.k is valid and the answer is unique → We don't need to handle ties or invalid k values.Count how often each element appears, then sort the unique elements by frequency and take the top k.
A hash map counts frequencies in one pass. We then sort the unique elements by their frequency in descending order. The first k elements in the sorted list are the answer.
freq where each key is an element from nums and the value is its count.k elements from the sorted list.This sorts all unique elements when we only need the top k. The next approach tracks only k elements at a time, lowering the cost of the selection step.
Instead of sorting all unique elements, maintain a min-heap of size k. The heap holds the k most frequent elements seen so far. When a new element arrives, compare its frequency to the smallest frequency in the heap. If it's larger, evict the minimum and insert the new one.
A min-heap, not a max-heap, is the right choice here. The minimum frequency among the current top k candidates sits at the top of a min-heap, so removing the weakest candidate is an O(log k) operation. Any element still in the heap after processing every unique element has a frequency at least as high as every element that was evicted, so the final heap contents are the k most frequent.
nums.Every unique element still costs a log k heap operation. The final approach removes the logarithmic factor by bucketing elements directly by their frequency.
The maximum frequency any element can have is n, the length of the array. So we can create an array of buckets where bucket[i] holds all elements that appear exactly i times. Walking from the highest bucket down and collecting elements gives the most frequent ones first.
This eliminates sorting and heap operations. The bucket array has size n+1, placing an element into its bucket is O(1), and walking the buckets from the end visits at most n+1 indices. The whole thing runs in O(n) time.
nums.buckets of size n+1, where buckets[i] is a list of elements with frequency i.