问题描述:
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.
注意: 给定的数组是无序的。 有下面两种方法,分别进行介绍。
- 思路1: Bucket sort(map+bucket_sort)
Step1: 使用map<int , int >统计每个数在数组中出现的次数。
Step2: 借用桶排序的思想, 申请 sizeof(array)+1 个桶(因为数组中出现频次最多可能就是 sizeof(array)+1) 。 桶是频次n, 桶内存放的是出现频次为n的数组元素 arr1, arr2…arrx。
Step3: 从后往前遍历桶,依次将桶内的元素取出来放到向量里,直到向量的个数为k。
1 class Solution { 2 public: 3 vector<int> topKFrequent(vector<int>& nums, int k) { 4 map<int,int> num_freq; 5 6 //step1 7 for (int num : nums) 8 num_freq[num]++; 9 vector<vector<int>> buckets(nums.size()+1); 10 //step2 11 for (auto bucket: num_freq) 12 buckets[bucket.second].push_back(bucket.first); 13 //step3 14 vector<int> val; 15 for (int i=(int)buckets.size()-1; i>=0 && val.size()<k; i--) 16 { 17 for(auto eachBucket : buckets[i]) 18 { 19 val.push_back(eachBucket); 20 if (val.size()>=k) 21 break; 22 } 23 24 } 25 return val; 26 } 27 };
总结: 空间复杂度:O(n), 时间复杂度:O(n)(n为数组元素的个数)
- 思路2: Heap Sort
借用priotity queue维持一个最小堆,其中堆的大小为K。 若堆的大小大于K, 则调整出列。
1 vector<int> topKFrequent(vector<int>& nums, int k) { 2 priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq; 3 4 map<int,int> cnt; 5 for (auto count : nums) cnt[count]++; 6 7 for (auto km : cnt) 8 { 9 pq.push({km.second,km.first}); 10 if(pq.size()>k) 11 pq.pop(); 12 } 13 14 vector<int> res; 15 while (!pq.empty()) 16 { 17 res.push_back(pq.top().second); 18 pq.pop(); 19 } 20 return res; 21 }
时间复杂度: O(Nlogk)
上面的堆排序结果是不稳定的,比如 原始向量是 {1,1,1,2,2,3} ,输出的值是{2,1}, 而并不是我们预期的{1, 2}。
若想得到稳定的排序结果,该怎么做呢?
可以使用最大堆,堆的大小为map.size()-k。若超过map.size()-k, 则将堆的最大值放入向量里。
1 vector<int> topKFrequent(vector<int>& nums, int k) { 2 map<int,int> counts; 3 for(int num:nums) 4 counts[num]++; 5 6 priority_queue<pair<int,int>> pq; 7 8 vector<int> res; 9 for(auto ct: counts) 10 { 11 pq.push({ct.second, ct.first}); 12 if(pq.size()>(counts.size()-k)) 13 { 14 res.push_back(pq.top().second); 15 pq.pop(); 16 } 17 } 18 return res; 19 }