Top K Frequent Elements

Solve this Problem
Medium20–25 min
Topics
Companies
Practice:LeetCode ↗GFG ↗
Given an array of integers and an integer k, return the k values that occur most often — ordered by frequency, highest first, with ties broken by the smaller value. Sorting every distinct value by frequency works, but frequency itself is a bounded number (a value can appear at most n times), which is exactly the situation bucket sort is built for: instead of comparing values against each other, drop each one straight into the bucket matching its count, then read the buckets off from highest to lowest.

Test Case 1:

Input:nums = [4, 4, 6, 6, 6, 2, 9, 9, 9, 9], k = 2
Output:[9, 6]
Explanation:9 appears 4 times, 6 appears 3 times — the two most frequent.

Test Case 2:

Input:nums = [5], k = 1
Output:[5]
Explanation:A single element is trivially the most frequent.

Test Case 3:

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

Constraints

  • 1 ≤ nums.length ≤ 100
  • -100 ≤ nums[i] ≤ 100
  • 1 ≤ k ≤ number of distinct values in nums
  • The result is ordered by frequency, highest first; values with equal frequency are ordered by value, smallest first, so the answer is always unique
🚀

Try the Dry Run

Don't just read the solution — watch it execute, one step at a time.

Approach & Solutions

Brute Force — Count, Then Fully Sort

Good

Count how often each value appears using a hash map, then sort every distinct value by frequency (highest first, ties broken by value) and keep the first k. Simple and correct, but it fully sorts every distinct value even though only the top k are ever needed.

TimeO(n log n)
SpaceO(n)
1class Solution { 2 public int[] topKFrequent(int[] nums, int k) { 3 Map<Integer, Integer> freq = new HashMap<>(); 4 for (int num : nums) { 5 freq.merge(num, 1, Integer::sum); 6 } 7 List<Integer> values = new ArrayList<>(freq.keySet()); 8 values.sort((a, b) -> freq.get(a).equals(freq.get(b)) ? a - b : freq.get(b) - freq.get(a)); 9 int[] result = new int[k]; 10 for (int i = 0; i < k; i++) { 11 result[i] = values.get(i); 12 } 13 return result; 14 } 15}

Optimal — Bucket Sort by Frequency

Optimal

Count frequencies the same way, but instead of sorting every distinct value, create one bucket per possible frequency (1 through n) and drop each value into the bucket matching its count. Then walk the buckets from the highest frequency down, collecting values until k of them have been gathered. Since a value can never appear more than n times, there are at most n buckets — no comparison-based sort is needed at all.

TimeO(n)
SpaceO(n)
1class Solution { 2 public int[] topKFrequent(int[] nums, int k) { 3 Map<Integer, Integer> freq = new HashMap<>(); 4 for (int num : nums) { 5 freq.merge(num, 1, Integer::sum); 6 } 7 int maxFreq = 0; 8 for (int f : freq.values()) maxFreq = Math.max(maxFreq, f); 9 List<List<Integer>> buckets = new ArrayList<>(); 10 for (int i = 0; i <= maxFreq; i++) buckets.add(new ArrayList<>()); 11 for (Map.Entry<Integer, Integer> e : freq.entrySet()) { 12 buckets.get(e.getValue()).add(e.getKey()); 13 } 14 List<Integer> result = new ArrayList<>(); 15 for (int f = maxFreq; f >= 1 && result.size() < k; f--) { 16 for (int val : buckets.get(f)) { 17 if (result.size() < k) result.add(val); 18 } 19 } 20 result.sort((a, b) -> freq.get(a).equals(freq.get(b)) ? a - b : freq.get(b) - freq.get(a)); 21 int[] output = new int[result.size()]; 22 for (int i = 0; i < result.size(); i++) output[i] = result.get(i); 23 return output; 24 } 25}

Related Problems