150NeetCode 150

5.Top K Frequent Elements

MediumBlind 75Arrays & Hashing ยท 5/9

Problem

Given an integer array nums and an integer k, return the k most frequent elements. The answer may be returned in any order.

The test data guarantees the answer is unique: there is never a tie at the boundary between the k-th and (k+1)-th most frequent values.

Examples

Input:  nums = [1, 1, 1, 2, 2, 3], k = 2
Output: [1, 2]
Explanation: 1 appears 3 times, 2 appears 2 times, 3 appears once.
Input:  nums = [1], k = 1
Output: [1]
Input:  nums = [4, 4, 5, 5, 5, 6], k = 1
Output: [5]

Constraints

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • k is in the range [1, number of unique elements].
  • The answer is guaranteed to be unique.
  • Follow-up: do better than O(n log n).

๐Ÿ’ก Key Insight

First count frequencies with a HashMap. The question then becomes "pick the k keys with the largest counts". Sorting all keys is O(n log n); a min-heap of size k is O(n log k). But a frequency can never exceed n, so we can use bucket sort: an array where bucket[f] lists the numbers occurring exactly f times, then read buckets from high to low โ€” O(n) total.

Sort by Frequency

TimeO(n log n)SpaceO(n)

Intuition

Count each value, put the distinct values in a list, sort that list by count descending, and take the first k.

Algorithm

  1. Build count: value โ†’ frequency.
  2. Copy the keys into a list and sort by count.get(x) descending.
  3. Return the first k entries.

Visualization

nums = [1,1,1,2,2,3]
count = {1:3, 2:2, 3:1}
sorted by count desc: [1(3), 2(2), 3(1)]
take k=2 โ†’ [1, 2]

Code

java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : nums) {
            count.merge(num, 1, Integer::sum);
        }
        List<Integer> keys = new ArrayList<>(count.keySet());
        // Highest frequency first
        keys.sort((a, b) -> Integer.compare(count.get(b), count.get(a)));
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = keys.get(i);
        }
        return result;
    }
}

Complexity

  • Time: O(n log n) โ€” counting is O(n); sorting up to n distinct keys is O(n log n).
  • Space: O(n) โ€” the map and key list.

Complexity Comparison

Approach Time Space
Sort by Frequency O(n log n) O(n)
Min-Heap of Size k O(n log k) O(n + k)
Bucket Sort O(n) O(n)

Common Pitfalls

  • Using a max-heap of all elements and popping k times works but is O(n log n) to build via repeated offers โ€” the size-k min-heap is the intended heap solution.
  • Sizing buckets as n instead of n + 1 โ€” when every element is the same value, its frequency is n and bucket[n] must exist.
  • Writing a - b in comparators can overflow in general; Integer.compare is safe.
  • Iterating over nums (with duplicates) instead of count.keySet() when filling the heap or buckets inserts the same value multiple times.