题目:Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements.
For example,
Given [1,1,1,2,2,3]
and k = 2, return [1,2]
.
Note:
- You may assume k is always valid, 1 ? k ? number of unique elements.
- Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
题意:给定一个非空整数数组,返回频度最大的k个元素。
要求复杂度要小于O(nlogn)
思路:
首先,需要求出每个数的频度,可以使用map,这样只用遍历数组一次,就求出每个数的频度。
然后找到频度最大的k个元素,返回。
如何找到频度最大的k个元素呢?
最直接的思路就是对上面得到的频度排序,这样就能得到频度最大的k个元素,但是排序算法的复杂度可能会变成O(n^2)。
因此,应该还有更好的方法。
我的思路是使用优先队列,保证队列中元素数量最大只有k个,这样直接返回优先队列中的元素就可以了。
而且,优先队列会自动根据一个值排序,我希望按照频度来排序。
当优先队列中已有k个元素时,每次新的元素要和频度最小的元素比较,取频度较大的元素。这样优先队列顶端的必须是频度最小的元素,所以我去频度的负数来做比较。
优先队列是使用堆来实现的,每次插入元素是一个调整堆的过程,时间复杂度是O(logn)。所以这样时间复杂度必然是小于O(nlogn)的。
vector<int> topKFrequent(vector<int>& nums, int k){ unordered_map<int, int>frequents; for (auto i : nums) ++frequents[i];//求出每个数的频度 priority_queue<pair<int, int>>largerK;//first是频度的负数,这样保证top得到的是频度最小的 auto it = frequents.begin(); while (it != frequents.end()){ if (largerK.size() < k)largerK.push({ -(it->second), it->first });//添加前k个元素 else if(it->second > -(largerK.top().first)){//替换频度最小的 largerK.pop(); largerK.push({ -(it->second), it->first }); } ++it; } vector<int>result; while (!largerK.empty()){//将k个数赋给数组 result.push_back(largerK.top().second); largerK.pop(); } return result; }