347. Top K Frequent Elements
mediumAsked at AirbnbGiven an integer array and integer k, return the k most frequent elements. Airbnb asks this to test whether you reach for bucket sort or a min-heap — both beat the naive sort.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Airbnb loops.
- Glassdoor (2026-Q1)— Airbnb L4 onsite reports list this as a recurring heap medium.
- Blind (2025-12)— Recurring in Airbnb backend interview reports.
Problem
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order. Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
Constraints
1 <= nums.length <= 10^5-10^4 <= nums[i] <= 10^4k is in the range [1, the number of unique elements in the array].It is guaranteed that the answer is unique.
Examples
Example 1
nums = [1,1,1,2,2,3], k = 2[1,2]Example 2
nums = [1], k = 1[1]Approaches
1. Sort by frequency (baseline)
Build a frequency map, sort unique elements by frequency descending, take the first k.
- Time
- O(n log n)
- Space
- O(n)
function topKFrequentSort(nums, k) {
const count = new Map();
for (const x of nums) count.set(x, (count.get(x) || 0) + 1);
return [...count.entries()].sort((a, b) => b[1] - a[1]).slice(0, k).map(e => e[0]);
}Tradeoff: Doesn't meet the better-than-O(n log n) requirement. Mention before pivoting.
2. Min-heap of size k
Build frequency map. Push entries into a min-heap; when size exceeds k, pop. The heap holds the top k.
- Time
- O(n log k)
- Space
- O(n + k)
class MinHeap {
constructor() { this.data = []; }
push(x) { this.data.push(x); let i = this.data.length - 1; while (i > 0) { const p = (i - 1) >> 1; if (this.data[p][1] <= this.data[i][1]) break; [this.data[p], this.data[i]] = [this.data[i], this.data[p]]; i = p; } }
pop() { const t = this.data[0]; const last = this.data.pop(); if (this.data.length) { this.data[0] = last; let i = 0; while (true) { let l = 2*i+1, r = 2*i+2, best = i; if (l < this.data.length && this.data[l][1] < this.data[best][1]) best = l; if (r < this.data.length && this.data[r][1] < this.data[best][1]) best = r; if (best === i) break; [this.data[best], this.data[i]] = [this.data[i], this.data[best]]; i = best; } } return t; }
size() { return this.data.length; }
}
function topKFrequent(nums, k) {
const count = new Map();
for (const x of nums) count.set(x, (count.get(x) || 0) + 1);
const heap = new MinHeap();
for (const [num, freq] of count) {
heap.push([num, freq]);
if (heap.size() > k) heap.pop();
}
return heap.data.map(e => e[0]);
}Tradeoff: O(n log k) beats O(n log n) when k is small. Cleaner than bucket sort if you've already implemented the heap.
3. Bucket sort by frequency (optimal in practice)
Build a frequency map. Create buckets[freq] -> list of nums with that frequency. Walk buckets from highest freq to lowest, taking the first k.
- Time
- O(n)
- Space
- O(n)
function topKFrequentBucket(nums, k) {
const count = new Map();
for (const x of nums) count.set(x, (count.get(x) || 0) + 1);
const buckets = Array.from({ length: nums.length + 1 }, () => []);
for (const [num, freq] of count) buckets[freq].push(num);
const result = [];
for (let i = buckets.length - 1; i >= 0 && result.length < k; i--) {
for (const num of buckets[i]) { result.push(num); if (result.length === k) break; }
}
return result;
}Tradeoff: Linear time because each unique element appears in exactly one bucket. Wins when k is close to n; both work.
Airbnb-specific tips
Airbnb's bar is naming the better-than-n-log-n requirement and choosing accordingly. Heap is the safer interview answer because it generalizes; bucket sort is cleaner if you spot that frequencies are bounded by n. Either way, articulate WHY you chose your approach.
Common mistakes
- Sorting the entire frequency map (O(n log n)) and not meeting the time bound.
- Using a max-heap of size n instead of a min-heap of size k.
- In bucket sort, buckets need to be of size n+1 (max possible freq is n).
Follow-up questions
An interviewer at Airbnb may pivot to one of these next:
- Top K Frequent Words (LC 692) — strings instead of ints, with lexicographic tie-break.
- K Closest Points to Origin (LC 973) — same heap pattern.
- Kth Largest Element in an Array (LC 215) — quickselect O(n) average.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Heap or bucket — which does Airbnb prefer?
Both pass with clear narration. Heap is the more reusable template; bucket sort is the 'clever O(n)' answer when frequencies are bounded.
Why log k and not log n in the heap version?
The heap holds at most k elements at all times. Push/pop on a k-heap is log k. We do that n times -> O(n log k).
Free learning resources
Curated free links for this problem.
Practice these live with InterviewChamp.AI
Drill Top K Frequent Elements and other Airbnb interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →