Code โบ algorithm-study
LeetCode 347 - Top K Frequent Elements
Using frequency counting and bucket arrays to return the top k frequent elements
This is a Medium array problem: return the k most frequent values. Sorting by frequency works, but this solution uses bucket arrays where the frequency itself becomes the bucket index.
Problem link and explanation
- Problem link: 347. Top K Frequent Elements
- Summary: Given an integer array nums and an integer k, return the k values that appear most often.
For example:
nums = [1, 1, 1, 2, 2, 3]
k = 2
The value 1 appears three times, and 2 appears twice, so the result can be [1, 2]. The order does not matter.
Approach
First, count how often each value appears.
freq_map = {}
for num in nums:
freq_map[num] = freq_map.get(num, 0) + 1
Then create buckets where the index represents the frequency. If the length of nums is n, no value can appear more than n times, so n + 1 buckets are enough.
buckets = [[] for i in range(len(nums) + 1)]
for num, freq in freq_map.items():
buckets[freq].append(num)
Finally, scan the buckets from high frequency to low frequency and return as soon as k values are collected.
top_list = []
for i in range(len(nums), -1, -1):
for num in buckets[i]:
top_list.append(num)
if len(top_list) == k:
return top_list
The point is to avoid comparing every value by frequency during sorting. A value with frequency 3 goes into buckets[3], a value with frequency 2 goes into buckets[2], and scanning backward visits higher-frequency values first.
Complexity analysis
-
Time complexity: O(n)
- One pass counts frequencies, one pass fills buckets, and the final scan is linear in the bucket array and collected values.
-
Space complexity: O(n)
- The frequency map and bucket array both scale with the input size.
Sorting by frequency usually costs O(n log n). The bucket array solution stays linear by using the bounded frequency range from 0 to n.
Optimized code
from typing import List
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
freq_map = {}
for num in nums:
freq_map[num] = freq_map.get(num, 0) + 1
buckets = [[] for _ in range(len(nums) + 1)]
for num, freq in freq_map.items():
buckets[freq].append(num)
top_list = []
for i in range(len(nums), -1, -1):
for num in buckets[i]:
top_list.append(num)
if len(top_list) == k:
return top_list
return top_list
Summary and reflection
Counting frequencies with a hash map is the straightforward first step. Sorting by frequency works, but because the maximum frequency is bounded by the length of nums, the counts can be moved into buckets and the solution can stay at O(n) time without sorting.