Top K Frequent Elements Using Heap in DSA Python - Time & Space Complexity
We want to find the most frequent items in a list efficiently. Understanding time complexity helps us see how the solution scales when the list grows.
How does the time needed change as the list gets bigger?
Analyze the time complexity of the following code snippet.
from collections import Counter
import heapq
def top_k_frequent(nums, k):
count = Counter(nums) # Count frequencies
heap = []
for num, freq in count.items():
heapq.heappush(heap, (freq, num))
if len(heap) > k:
heapq.heappop(heap)
return [num for freq, num in heap]
This code finds the k most frequent numbers in the list using a min-heap.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping over unique numbers to push and pop from the heap.
- How many times: Once for each unique number in the list.
As the list grows, counting frequencies takes longer, and managing the heap depends on unique numbers.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Counting ~10, Heap ops ~unique count |
| 100 | Counting ~100, Heap ops ~unique count |
| 1000 | Counting ~1000, Heap ops ~unique count |
Pattern observation: Counting grows linearly with input size, heap operations grow with unique elements, which is usually less than total input.
Time Complexity: O(n + u log k)
This means counting all elements takes time proportional to the list size, and managing the heap depends on the number of unique elements and k.
[X] Wrong: "The heap operations take O(n log n) because we push all elements into the heap."
[OK] Correct: We only push unique elements, not all list items, and keep heap size limited to k, so heap operations depend on unique count and k, not total n.
Understanding how to combine counting and heap operations shows you can handle data efficiently. This skill is useful for many real-world problems where you need top results quickly.
"What if we used a max-heap for all elements instead of a min-heap limited to size k? How would the time complexity change?"
Practice
Top K Frequent Elements problem?Solution
Step 1: Understand the problem goal
The problem asks to find the k elements that appear most frequently in a list.Step 2: Role of heap in this context
A heap helps efficiently keep track of the top k frequent elements by maintaining a small structure of size k, allowing quick access to the smallest frequency among them.Final Answer:
To efficiently keep track of the top k elements by frequency -> Option AQuick Check:
Heap = Efficient top k tracking [OK]
- Thinking heap sorts all elements fully
- Confusing heap with simple list or set
- Assuming heap removes duplicates
freq_list using the heapq module?Solution
Step 1: Recall heapq module functions
Theheapqmodule providesheapify()to convert a list into a heap in-place.Step 2: Identify correct function usage
Onlyheapq.heapify(freq_list)is valid syntax to create a min-heap from a list.Final Answer:
import heapq heapq.heapify(freq_list) -> Option BQuick Check:
heapify() creates heap [OK]
- Using non-existent heapq functions
- Confusing heapify with sorting
- Missing import statement
import heapq
nums = [1,1,1,2,2,3]
count = {}
for n in nums:
count[n] = count.get(n, 0) + 1
heap = []
for num, freq in count.items():
heapq.heappush(heap, (freq, num))
result = []
for _ in range(2):
result.append(heapq.heappop(heap)[1])
print(result)Solution
Step 1: Count frequencies of elements
nums = [1,1,1,2,2,3] gives count = {1:3, 2:2, 3:1}.Step 2: Push (freq, num) into min-heap and pop twice
Heap contains (3,1), (2,2), (1,3). Popping twice removes smallest freq first: (1,3), then (2,2). So result = [3, 2].Final Answer:
[3, 2] -> Option DQuick Check:
Lowest freq elements popped first = [3, 2] [OK]
- Assuming heap pops highest frequency first
- Mixing up element and frequency order
- Not counting frequencies correctly
import heapq
nums = [4,4,4,5,5,6]
count = {}
for n in nums:
count[n] = count.get(n, 0) + 1
heap = []
for num, freq in count.items():
heapq.heappush(heap, (num, freq))
result = []
for _ in range(2):
result.append(heapq.heappop(heap)[1])
print(result)Solution
Step 1: Check tuple order pushed to heap
The heap is a min-heap by first tuple element. Pushing (num, freq) orders by num, not frequency.Step 2: Correct tuple order for frequency sorting
To get top frequent elements, push (freq, num) so heap orders by frequency.Final Answer:
The tuple pushed to heap should be (freq, num), not (num, freq) -> Option CQuick Check:
Heap order depends on first tuple element [OK]
- Swapping frequency and element in tuple
- Using wrong heapq function name
- Incorrect loop range for popping
nums = [2,3,2,4,3,3,5,5,5,5] and k = 2, which of the following code snippets correctly returns the top k frequent elements using a heap?Solution
Step 1: Understand the problem and approach
We want top k frequent elements using a min-heap of size k to keep track of highest frequencies.Step 2: Analyze each option
import heapq count = {} for n in nums: count[n] = count.get(n, 0) + 1 heap = [] for num, freq in count.items(): if len(heap) < k: heapq.heappush(heap, (freq, num)) else: if freq > heap[0][0]: heapq.heapreplace(heap, (freq, num)) result = [num for freq, num in heap] print(result) correctly pushes (freq, num) and maintains heap size k, replacing smallest freq when a bigger freq is found. import heapq count = {} for n in nums: count[n] = count.get(n, 0) + 1 heap = [] for num, freq in count.items(): heapq.heappush(heap, (num, freq)) result = [heapq.heappop(heap)[1] for _ in range(k)] print(result) pushes (num, freq) which is wrong order. import heapq count = {} for n in nums: count[n] = count.get(n, 0) + 1 heap = [] for num, freq in count.items(): heapq.heappush(heap, (-freq, num)) result = [heapq.heappop(heap)[1] for _ in range(k)] print(result) uses negative freq but does not maintain heap size k properly. import heapq count = {} for n in nums: count[n] = count.get(n, 0) + 1 heap = [] for num, freq in count.items(): if freq < k: heapq.heappush(heap, (freq, num)) result = [num for freq, num in heap] print(result) pushes only if freq < k which is incorrect logic.Final Answer:
Option A code correctly returns top k frequent elements -> Option AQuick Check:
Min-heap size k with freq as key [OK]
- Pushing wrong tuple order to heap
- Not limiting heap size to k
- Using negative frequencies without proper logic
Ready to prove it?
Pass the test and this pattern moves unknown
