347. Top K Frequent Elements
mediumAsked at AmazonGiven an array of numbers and integer k, return the k most frequent elements. Amazon asks this to test whether you reach for bucket sort or heap and can articulate the n log k vs O(n) tradeoff.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Amazon loops.
- Glassdoor (2026-Q1)— Amazon SDE I/II onsite reports cite this as a recurring hash + heap problem.
- Blind (2025-12)— Recurring Amazon interview question.
Problem
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
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. Hash + sort
Count occurrences. Sort entries by count descending. Take top k.
- Time
- O(n log n)
- Space
- O(n)
function topKFrequentSort(nums, k) {
const counts = new Map();
for (const n of nums) counts.set(n, (counts.get(n) || 0) + 1);
return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, k).map(e => e[0]);
}Tradeoff: Easy to write. Mention before offering the better solutions.
2. Min-heap of size k
Count, then push each (count, val) onto a min-heap. Pop when size > k. Result is the heap contents.
- Time
- O(n log k)
- Space
- O(n + k)
class MinHeap {
constructor() { this.data = []; }
push(v) { this.data.push(v); this._up(this.data.length - 1); }
pop() { if (!this.data.length) return; const top = this.data[0]; const last = this.data.pop(); if (this.data.length) { this.data[0] = last; this._down(0); } return top; }
size() { return this.data.length; }
_up(i) { while (i > 0) { const p = (i - 1) >> 1; if (this.data[p][0] <= this.data[i][0]) break; [this.data[p], this.data[i]] = [this.data[i], this.data[p]]; i = p; } }
_down(i) { while (true) { const l = 2*i+1, r = 2*i+2; let best = i; if (l < this.data.length && this.data[l][0] < this.data[best][0]) best = l; if (r < this.data.length && this.data[r][0] < this.data[best][0]) best = r; if (best === i) break; [this.data[best], this.data[i]] = [this.data[i], this.data[best]]; i = best; } }
}
function topKFrequentHeap(nums, k) {
const counts = new Map();
for (const n of nums) counts.set(n, (counts.get(n) || 0) + 1);
const heap = new MinHeap();
for (const [val, cnt] of counts) {
heap.push([cnt, val]);
if (heap.size() > k) heap.pop();
}
return heap.data.map(x => x[1]);
}Tradeoff: Better than sort when k << n. Common interview answer.
3. Bucket sort (optimal)
Count occurrences. Place each value into a bucket indexed by its count. Walk buckets from highest count down, collecting until k items.
- Time
- O(n)
- Space
- O(n)
function topKFrequent(nums, k) {
const counts = new Map();
for (const n of nums) counts.set(n, (counts.get(n) || 0) + 1);
const buckets = Array.from({ length: nums.length + 1 }, () => []);
for (const [val, cnt] of counts) buckets[cnt].push(val);
const result = [];
for (let i = buckets.length - 1; i >= 0 && result.length < k; i--) {
for (const v of buckets[i]) {
result.push(v);
if (result.length === k) return result;
}
}
return result;
}Tradeoff: True O(n) because counts are bounded by n. Bucket sort works because counts are integers in [1, n] — no comparison sorting needed.
Amazon-specific tips
Amazon interviewers grade this on whether you can articulate three approaches and pick. State out loud: 'Sort is O(n log n). Min-heap of size k is O(n log k). Bucket sort is O(n) because counts are bounded.' Then pick. Bucket sort is the highest-bar answer; heap is the most-common.
Common mistakes
- Building a max-heap and popping k times — works but is O(n + k log n), not O(n log k).
- Forgetting that counts are in [1, n] — bucket size = nums.length + 1.
- Using O(n^2) brute-force per query when k is small (not the actual ask).
Follow-up questions
An interviewer at Amazon may pivot to one of these next:
- Top K Frequent Words (LC 692) — adds a lexicographic tiebreaker.
- K Closest Points to Origin (LC 973) — same heap/quickselect pattern.
- What if the array is a stream?
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why does bucket sort work here?
Counts are integers in [1, n]. Bucket sort works when keys are bounded integers — no comparison sorting needed.
Heap or bucket sort — which is preferred?
Bucket sort scores higher (O(n) vs O(n log k)). Heap is more general (works for any comparable type) — lead with heap, then offer bucket sort if asked for O(n).
Practice these live with InterviewChamp.AI
Drill Top K Frequent Elements and other Amazon interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →