好久不刷题了,今晚来一道。
题目
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.
思路
题目中明确提示要O(nlogn)复杂度了…
我的做法是先统计结果到一个map<value, count>里面,然后用一个大小为k的最小堆处理,每次从map中读取元素时根据count值判断是否要替换掉堆顶。由于STL的map是用红黑树实现的,所以时间复杂度就保证了,要再快的话就直接用hash函数吧,可以到O(n)。维护k大小的堆,算最差情况,建堆复杂度是O(k),维护复杂度是O(logk), 要维护M-k次,其中0<M<=N是map中的元素个数.
代码
struct CountVal{
int val;
int count;
CountVal(int _val, int _count){
val = _val;
count = _count;
}
};
bool compareObj(const CountVal& x, const CountVal& y){
return x.count > y.count;
}
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> countMap;
vector<CountVal> counts;
for(int i=0; i<nums.size(); i++){
if(countMap.count(nums[i]) == 0)
countMap[nums[i]] = 1;
else
countMap[nums[i]]++;
}
int count = 0;
for(auto it=countMap.begin(); it!=countMap.end(); it++){
CountVal item(it->first, it->second);
if(count < k){
counts.push_back(item);
if(count == k-1){
make_heap(counts.begin(), counts.end(), compareObj);
}
} else {
if (it->second > counts.front().count) {
pop_heap(counts.begin(), counts.end(), compareObj);
counts.pop_back();
counts.push_back(item);
push_heap(counts.begin(), counts.end(), compareObj);
}
}
count++;
}
vector<int> results;
for(auto it=counts.begin(); it!=counts.end(); it++){
results.push_back(it->val);
}
return results;
}
};