🧠
Better Approach (Frequency Map + Min-Heap)
💡 This approach improves efficiency by using a min-heap to keep track of the top k frequent elements without sorting all unique elements.
Intuition
Count frequencies, then maintain a min-heap of size k to store the top k elements by frequency. This avoids sorting all elements.
Algorithm
- Count the frequency of each element using a hash map.
- Create a min-heap to store elements by frequency.
- Iterate over frequency map, push elements into the heap.
- If heap size exceeds k, pop the smallest frequency element.
- After processing all, extract elements from heap as result.
💡 Using a min-heap keeps only the top k frequent elements, reducing sorting overhead.
from typing import List
import heapq
def topKFrequent(nums: List[int], k: int) -> List[int]:
freq = {}
for num in nums:
freq[num] = freq.get(num, 0) + 1
heap = []
for num, count in freq.items():
heapq.heappush(heap, (count, num))
if len(heap) > k:
heapq.heappop(heap)
return [num for count, num in heap]
# Driver code
if __name__ == '__main__':
print(topKFrequent([1,1,1,2,2,3], 2)) # Output: [2, 1]
Line Notes
freq = {}Initialize frequency dictionary
for num in nums:Count frequency of each number
heap = []Initialize min-heap to track top k elements
heapq.heappush(heap, (count, num))Push current element with frequency into heap
if len(heap) > k:If heap exceeds size k, remove smallest frequency element
return [num for count, num in heap]Extract elements from heap as result
import java.util.*;
public class Solution {
public static List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> freq = new HashMap<>();
for (int num : nums) {
freq.put(num, freq.getOrDefault(num, 0) + 1);
}
PriorityQueue<Map.Entry<Integer, Integer>> heap = new PriorityQueue<>(
Comparator.comparingInt(Map.Entry::getValue));
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
heap.offer(entry);
if (heap.size() > k) {
heap.poll();
}
}
List<Integer> res = new ArrayList<>();
while (!heap.isEmpty()) {
res.add(heap.poll().getKey());
}
Collections.reverse(res); // Reverse to match descending frequency order
return res;
}
public static void main(String[] args) {
System.out.println(topKFrequent(new int[]{1,1,1,2,2,3}, 2)); // Output: [1, 2]
}
}
Line Notes
Map<Integer, Integer> freq = new HashMap<>();Create frequency map
for (int num : nums)Count frequencies
PriorityQueue<Map.Entry<Integer, Integer>> heap = new PriorityQueue<>(...)Min-heap based on frequency
heap.offer(entry);Add entry to heap
if (heap.size() > k)Maintain heap size at most k
while (!heap.isEmpty())Extract top k elements from heap
Collections.reverse(res);Reverse result to get descending frequency order
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> freq;
for (int num : nums) {
freq[num]++;
}
// Comparator for min-heap by frequency
auto cmp = [&](pair<int,int>& a, pair<int,int>& b) { return a.first > b.first; };
priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(cmp)> heap(cmp);
for (auto& p : freq) {
heap.push({p.second, p.first});
if ((int)heap.size() > k) heap.pop();
}
vector<int> res;
while (!heap.empty()) {
res.push_back(heap.top().second);
heap.pop();
}
reverse(res.begin(), res.end()); // Reverse to get descending frequency order
return res;
}
int main() {
vector<int> nums = {1,1,1,2,2,3};
vector<int> res = topKFrequent(nums, 2);
for (int x : res) cout << x << ' ';
cout << '\n'; // Output: 1 2
return 0;
}
Line Notes
unordered_map<int, int> freq;Count frequencies using hash map
auto cmp = [&](pair<int,int>& a, pair<int,int>& b)Comparator for min-heap by frequency
priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(cmp)> heap(cmp);Min-heap to keep top k frequent elements
heap.push({p.second, p.first});Push frequency and element pair into heap
if ((int)heap.size() > k) heap.pop();Pop smallest frequency if heap size exceeds k
while (!heap.empty())Extract elements from heap for result
reverse(res.begin(), res.end());Reverse result to get descending frequency order
function topKFrequent(nums, k) {
const freq = new Map();
for (const num of nums) {
freq.set(num, (freq.get(num) || 0) + 1);
}
const heap = [];
const pushHeap = (pair) => {
heap.push(pair);
heap.sort((a, b) => a[0] - b[0]);
if (heap.length > k) heap.shift();
};
for (const [num, count] of freq.entries()) {
pushHeap([count, num]);
}
return heap.map(pair => pair[1]);
}
// Test
console.log(topKFrequent([1,1,1,2,2,3], 2)); // Output: [2, 1]
Line Notes
const freq = new Map();Initialize frequency map
for (const num of nums)Count frequencies
const heap = [];Use array as min-heap substitute
heap.push(pair);Add frequency-element pair to heap
heap.sort((a, b) => a[0] - b[0]);Sort heap to maintain min-heap property
if (heap.length > k) heap.shift();Remove smallest frequency element if heap too big
return heap.map(pair => pair[1]);Extract elements from heap as result
Counting frequencies is O(n). Each insertion into heap is O(log k), done for m unique elements, so O(m log k). Since m ≤ n, total O(n log k).
💡 For n=100,000 and k=10, this is much faster than sorting all elements.
Interview Verdict: Accepted and efficient for large inputs
This approach balances speed and simplicity, suitable for most interview scenarios.