Top K Frequent Elements Using Heap in DSA Java - Time & Space Complexity
We want to know how the time needed to find the top K frequent elements grows as the input list gets bigger.
How does the program's work increase when there are more numbers to check?
Analyze the time complexity of the following code snippet.
import java.util.*;
public List topKFrequent(int[] nums, int k) {
Map freqMap = new HashMap<>();
for (int num : nums) {
freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);
}
PriorityQueue heap = new PriorityQueue<>((a, b) -> freqMap.get(a) - freqMap.get(b));
for (int num : freqMap.keySet()) {
heap.offer(num);
if (heap.size() > k) {
heap.poll();
}
}
List result = new ArrayList<>();
while (!heap.isEmpty()) {
result.add(heap.poll());
}
Collections.reverse(result);
return result;
}
This code finds the top K numbers that appear most often in the input array using a heap.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Counting frequencies by looping through all numbers once.
- Secondary operation: Looping through unique numbers to add them to the heap.
- Heap operations: offer(num) for each unique number and poll() when size > k, each O(log k).
- How many times: The first loop runs n times (n = length of input), the second loop runs m times (m = number of unique elements).
As the input size grows, counting frequencies grows linearly with n. The heap operations depend on m and k.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 frequency counts + heap operations on up to 10 unique elements |
| 100 | About 100 frequency counts + heap operations on up to 100 unique elements |
| 1000 | About 1000 frequency counts + heap operations on up to 1000 unique elements |
Pattern observation: Counting grows directly with input size, heap operations grow with unique elements and k, which is usually smaller.
Time Complexity: O(n + m log k)
This means the time grows linearly with the input size plus the cost of managing the heap for unique elements, which depends on k.
[X] Wrong: "The heap operations take O(m log m) time because all unique elements are added to the heap."
[OK] Correct: The heap size is kept at most k, so each insertion or removal costs O(log k), not O(log m), making it faster than expected.
Understanding how to combine counting and heap operations efficiently shows you can handle real problems where you need to find top items quickly.
"What if we used a max-heap of size m instead of a min-heap of size k? How would the time complexity change?"
Practice
Top K Frequent Elements Using Heap problem?Solution
Step 1: Understand the role of a heap
A heap is a special tree-based data structure that helps quickly find the smallest or largest element.Step 2: Apply heap to top K frequent elements
Using a min-heap of size K allows us to keep track of the K elements with the highest frequency efficiently.Final Answer:
To efficiently keep track of the top K frequent elements by frequency -> Option AQuick Check:
Heap = Efficient top K tracking [OK]
- Thinking heap sorts all elements fully
- Using heap to remove duplicates
- Ignoring frequency counts
Solution
Step 1: Understand Java PriorityQueue default behavior
By default, PriorityQueue is a min-heap, ordering elements in ascending order.Step 2: Check comparator for min-heap with custom size
The comparator (a, b) -> a - b keeps the natural ascending order, suitable for min-heap.Final Answer:
PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b); -> Option DQuick Check:
Comparator a-b = min-heap [OK]
- Using reverseOrder() creates max-heap, not min-heap
- Wrong comparator sign reverses heap order
- Not specifying initial capacity k is okay but less efficient
int[] nums = {1,1,1,2,2,3};
int k = 2;
Map freqMap = new HashMap<>();
for (int num : nums) freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);
PriorityQueue<Integer> minHeap = new PriorityQueue<>((a, b) -> freqMap.get(a) - freqMap.get(b));
for (int key : freqMap.keySet()) {
minHeap.offer(key);
if (minHeap.size() > k) minHeap.poll();
}
List<Integer> result = new ArrayList<>();
while (!minHeap.isEmpty()) result.add(minHeap.poll());
Collections.reverse(result);
System.out.println(result);Solution
Step 1: Calculate frequencies
Frequencies: 1 -> 3 times, 2 -> 2 times, 3 -> 1 time.Step 2: Use min-heap to keep top 2 frequent elements
Heap keeps smallest frequency on top. Insert keys: 1(3), 2(2), 3(1). When size > 2, remove smallest frequency. After all insertions, heap contains 1 and 2.Step 3: Extract and reverse result
Polling heap gives [2,1], reversing gives [1,2].Final Answer:
[1, 2] -> Option BQuick Check:
Top 2 frequent = [1, 2] [OK]
- Not reversing the result list
- Confusing min-heap with max-heap behavior
- Ignoring frequency counts in comparator
int[] nums = {4,4,4,6,6,7};
int k = 2;
Map freqMap = new HashMap<>();
for (int num : nums) freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);
PriorityQueue<Integer> minHeap = new PriorityQueue<>((a, b) -> freqMap.get(b) - freqMap.get(a));
for (int key : freqMap.keySet()) {
minHeap.offer(key);
if (minHeap.size() > k) minHeap.poll();
}
List<Integer> result = new ArrayList<>();
while (!minHeap.isEmpty()) result.add(minHeap.poll());
System.out.println(result);Solution
Step 1: Analyze comparator in PriorityQueue
The comparator (a, b) -> freqMap.get(b) - freqMap.get(a) creates a max-heap (largest frequency on top).Step 2: Understand heap usage for top K frequent elements
We need a min-heap to remove the smallest frequency when size exceeds k, but max-heap removes largest, causing wrong elements to be removed.Step 3: Identify the error
The comparator should be (a, b) -> freqMap.get(a) - freqMap.get(b) for min-heap behavior.Final Answer:
Comparator reverses order causing max-heap instead of min-heap -> Option CQuick Check:
Wrong comparator = max-heap error [OK]
- Using max-heap instead of min-heap for top K
- Not reversing result list after polling
- Incorrect frequency counting
nums = {5,3,1,1,1,3,73,1} and k = 2, which approach correctly returns the top K frequent elements using a heap?
Choose the best sequence of steps.Solution
Step 1: Count frequencies of elements
Frequencies: 1 -> 4 times, 3 -> 2 times, 5 -> 1 time, 73 -> 1 time.Step 2: Use min-heap of size k with frequency comparator
Insert elements into min-heap; if size exceeds k, remove smallest frequency element to keep top k frequent elements.Step 3: Extract elements from heap for result
After processing, heap contains elements with highest frequencies: 1 and 3.Final Answer:
Count frequencies, use min-heap of size k with frequency comparator, add elements, remove smallest when size > k, then extract result -> Option AQuick Check:
Min-heap size k keeps top K frequent [OK]
- Using max-heap and polling k times is less efficient
- Sorting array ignores frequency counts
- Using hash set loses frequency info
Ready to prove it?
Pass the test and this pattern moves unknown
