Prompt
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
Examples
- 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] <= 104kis in the range[1, the number of unique elements in the array].- It is guaranteed that the answer is unique.
Solutions
Sorted Frequency Map Solution
In C++
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, size_t> freq;
for (int num : nums) freq[num]++;
vector<pair<int, int>> sorted_freq(freq.begin(), freq.end());
sort(
sorted_freq.begin(), sorted_freq.end(),
[](const pair<int, int>& a, const pair<int, int>& b) {
return a.second > b.second;
}
);
vector<int> topK(k);
for (int i = 0; i < k; ++i) topK[i] = sorted_freq[i].first;
return topK;
}Explanation
Create a frequency map of the elements of the input array, sort it, and take the first k and create the answer list from it.
Big O Analysis
Time Complexity
The average time complexity is because of the sorting, and the worst case is . Even if we used Quick Select here, which has a better average complexity of , the worst case is still .
Auxiliary Space Complexity
The space complexity is
Optimal Frequency Map Solution
In C++
vector<int> topKFrequent(vector<int>& nums, int k) {
// each num entry has a frequency
unordered_map<int, size_t> freq_by_num;
for (int num : nums) freq_by_num[num]++;
// each frequency entry has a list of nums
auto nums_by_freq = make_unique<vector<int>[]>(nums.size() + 1);
for (const auto& pair : freq_by_num) {
nums_by_freq[pair.second].push_back(pair.first);
}
// empty first k into answer
vector<int> topK;
for (int i = nums.size(); i > 0; --i) {
const auto& curr_vec = nums_by_freq[i];
if (!curr_vec.empty()) {
for (const auto& e : curr_vec) {
topK.push_back(e);
if (topK.size() == k) return topK;
}
}
}
return topK;
}Explanation
The idea here is that we still do a frequency map, but then from that, we create an array of lists of all numbers that had a certain frequency, where the index is equal to the frequency. Kind of like Radix Sort, because we know extra information about the nature of the data, we can abuse that knowledge to “sort” without needed to compare entries. The information that we know in this case is that the maximum frequency is the length of the input array, and the minimum is 0. Based on this principle, we can take the top K from the highest frequency list all the way down to the lowest, stopping when we have taken k elements.
Time Complexity
The time complexity is
Auxiliary Space Complexity
The space complexity is