Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
Example 3:
Input: nums = [1,2,1,2,1,2,3,1,3,2], k = 2
Output: [1,2]
Constraints:
1 <= nums.length <= 105-104 <= nums[i] <= 104k is in the range [1, the number of unique elements in the array].Follow up: Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
Problem summary: Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map
[1,1,1,2,2,3] 2
[1] 1
[1,2,1,2,1,2,3,1,3,2] 2
word-frequency)kth-largest-element-in-an-array)sort-characters-by-frequency)split-array-into-consecutive-subsequences)top-k-frequent-words)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #347: Top K Frequent Elements
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> cnt = new HashMap<>();
for (int x : nums) {
cnt.merge(x, 1, Integer::sum);
}
PriorityQueue<Map.Entry<Integer, Integer>> pq
= new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
for (var e : cnt.entrySet()) {
pq.offer(e);
if (pq.size() > k) {
pq.poll();
}
}
return pq.stream().mapToInt(Map.Entry::getKey).toArray();
}
}
// Accepted solution for LeetCode #347: Top K Frequent Elements
func topKFrequent(nums []int, k int) []int {
cnt := map[int]int{}
for _, x := range nums {
cnt[x]++
}
pq := hp{}
for x, c := range cnt {
heap.Push(&pq, pair{x, c})
if pq.Len() > k {
heap.Pop(&pq)
}
}
ans := make([]int, k)
for i := 0; i < k; i++ {
ans[i] = heap.Pop(&pq).(pair).v
}
return ans
}
type pair struct{ v, cnt int }
type hp []pair
func (h hp) Len() int { return len(h) }
func (h hp) Less(i, j int) bool { return h[i].cnt < h[j].cnt }
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v any) { *h = append(*h, v.(pair)) }
func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
# Accepted solution for LeetCode #347: Top K Frequent Elements
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
cnt = Counter(nums)
return [x for x, _ in cnt.most_common(k)]
// Accepted solution for LeetCode #347: Top K Frequent Elements
use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashMap};
impl Solution {
pub fn top_k_frequent(nums: Vec<i32>, k: i32) -> Vec<i32> {
let mut cnt = HashMap::new();
for x in nums {
*cnt.entry(x).or_insert(0) += 1;
}
let mut pq = BinaryHeap::with_capacity(k as usize);
for (&x, &c) in cnt.iter() {
pq.push(Reverse((c, x)));
if pq.len() > k as usize {
pq.pop();
}
}
pq.into_iter().map(|Reverse((_, x))| x).collect()
}
}
// Accepted solution for LeetCode #347: Top K Frequent Elements
function topKFrequent(nums: number[], k: number): number[] {
const cnt = new Map<number, number>();
for (const x of nums) {
cnt.set(x, (cnt.get(x) ?? 0) + 1);
}
const pq = new PriorityQueue<number[]>((a, b) => a[1] - b[1]);
for (const [x, c] of cnt) {
pq.enqueue([x, c]);
if (pq.size() > k) {
pq.dequeue();
}
}
return pq.toArray().map(x => x[0]);
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.