Top K Frequent Elements Using Heap in DSA C - Time & Space Complexity
We want to understand how the time needed to find the top K frequent elements changes as the input grows.
How does the program's work increase when the list of numbers gets bigger?
Analyze the time complexity of the following code snippet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Simple structure for heap nodes
typedef struct {
int num;
int freq;
} HeapNode;
// Function to find top K frequent elements
void topKFrequent(int* nums, int numsSize, int k) {
// Count frequencies (assume max number range for simplicity)
int freq[10000] = {0};
for (int i = 0; i < numsSize; i++) {
freq[nums[i]]++;
}
// Build a min-heap of size k for top frequencies
HeapNode heap[k];
int heapSize = 0;
for (int i = 0; i < 10000; i++) {
if (freq[i] > 0) {
if (heapSize < k) {
heap[heapSize++] = (HeapNode){i, freq[i]};
// heapify up omitted for brevity
} else if (freq[i] > heap[0].freq) {
heap[0] = (HeapNode){i, freq[i]};
// heapify down omitted for brevity
}
}
}
// Print top K elements
for (int i = 0; i < heapSize; i++) {
printf("%d ", heap[i].num);
}
printf("\n");
}
This code counts how often each number appears, then uses a small heap to keep track of the top K frequent numbers.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Counting frequencies by looping over all numbers once.
- Secondary operation: Looping over the frequency array to build and maintain a heap of size k.
- How many times: The first loop runs n times (n = number of input elements). The second loop runs up to m times (m = range of possible numbers, here 10,000).
- Heap operations: Each insertion or replacement in the heap costs about O(log k).
As the input size n grows, counting frequencies grows linearly.
Checking the frequency array depends on m, the range size, which is fixed here but could grow.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | ~10 + 10000 * log(k) |
| 100 | ~100 + 10000 * log(k) |
| 1000 | ~1000 + 10000 * log(k) |
Pattern observation: Counting grows directly with n, but heap operations depend on m and k, which may be smaller or fixed.
Time Complexity: O(n + m log k)
This means the time grows linearly with input size n plus the cost of managing a heap of size k over m unique elements.
[X] Wrong: "The time complexity is just O(n log n) because of sorting or heap operations on all elements."
[OK] Correct: We don't heapify all n elements, only the unique m elements, and the heap size is limited to k, which is usually much smaller than n.
Understanding how to combine counting with a heap is a great skill to show you can handle both data processing and efficient selection.
"What if we used a balanced binary search tree instead of a heap to keep track of top K elements? How would the time complexity change?"
Practice
Top K Frequent Elements Using Heap algorithm?Solution
Step 1: Understand the role of heap in frequency problems
A heap helps keep track of the most frequent elements efficiently by allowing quick access to the smallest or largest frequency element.Step 2: Identify why heap is used for top K elements
Using a min-heap of size K allows us to maintain only the top K frequent elements, removing less frequent ones as we go.Final Answer:
To efficiently find and maintain the top K frequent elements -> Option AQuick Check:
Heap = Efficient top K tracking [OK]
- Thinking heap sorts all elements fully
- Using heap to remove duplicates
- Ignoring frequency counts in heap
Solution
Step 1: Understand C++ priority_queue syntax for min-heap
By default, priority_queue is a max-heap. To make it min-heap, we use greater comparator.Step 2: Check the correct template parameters
We need a priority_queue of pairs, with vector as container, and greater> as comparator for min-heap.Final Answer:
priority_queue, vector>, greater>> minHeap; -> Option CQuick Check:
Min-heap = priority_queue with greater comparator [OK]
- Using default priority_queue which is max-heap
- Wrong comparator like less instead of greater
- Incorrect container type in priority_queue
#include
#include
#include
int main() {
int nums[] = {1,1,1,2,2,3};
int freq[4] = {0};
for(int i=0; i<6; i++) freq[nums[i]]++;
int k = 2;
int result[2];
int idx = 0;
for(int i=1; i<=3; i++) {
if(idx < k) {
result[idx++] = i;
} else {
int min_idx = 0;
for(int j=1; j freq[result[min_idx]]) result[min_idx] = i;
}
}
for(int i=0; iSolution
Step 1: Count frequencies of elements
nums = {1,1,1,2,2,3} so freq[1]=3, freq[2]=2, freq[3]=1.Step 2: Select top 2 frequent elements using simple logic
Initially result = {1,2}. For i=3, freq[3]=1 is less than min freq in result (which is freq[2]=2), so no replacement.Final Answer:
1 2 -> Option DQuick Check:
Top 2 frequent = 1 and 2 [OK]
- Confusing element values with frequencies
- Replacing elements incorrectly in result array
- Ignoring initial filling of result array
#include
#include
#include <queue>
#include <vector>
#include <unordered_map>
using namespace std;
int main() {
vector<int> nums = {4,4,4,6,6,7,7,7,7};
unordered_map freq;
for(auto n : nums) freq[n]++;
priority_queue, vector>, greater>> minHeap;
int k = 3;
for(auto it : freq) {
minHeap.push({it.second, it.first});
if(minHeap.size() > k) minHeap.pop();
}
while(!minHeap.empty()) {
printf("%d ", minHeap.top().second);
minHeap.pop();
}
return 0;
}Solution
Step 1: Understand min-heap stores (frequency, element)
Min-heap keeps smallest frequency on top, so popping prints from least to most frequent.Step 2: Identify output order issue
Printing while popping will print elements from lowest to highest frequency, not top frequent first.Final Answer:
The output order is reversed; elements print from least to most frequent -> Option BQuick Check:
Min-heap pop order = ascending frequency [OK]
- Confusing pair order in heap
- Wrong pop condition for heap size
- Ignoring output order from heap pops
nums = {5,3,1,1,1,3,73,1} and k = 2, which approach correctly finds the top K frequent elements using a heap and handles ties properly?Solution
Step 1: Count frequencies of elements
Frequencies: 1->4, 3->2, 5->1, 73->1.Step 2: Use min-heap of size k to keep top frequent elements
Insert pairs (freq, element). If heap size exceeds k, pop smallest frequency. This keeps top k frequent elements efficiently.Step 3: Handle ties by frequency naturally in heap
Elements with same frequency are handled by heap order; ties do not break correctness.Final Answer:
Use a min-heap of size k with (frequency, element) pairs, replacing when frequency is higher -> Option AQuick Check:
Min-heap size k keeps top frequent elements [OK]
- Using max-heap and popping k times without size limit
- Sorting array instead of frequencies
- Ignoring heap for frequency tracking
Ready to prove it?
Pass the test and this pattern moves unknown
