TopK问题
来源:互联网 发布:unity3d室内插件 编辑:程序博客网 时间:2024/05/16 18:18
1. 无序数组找最大的K个数
方法1: 排序+查找 时间复杂度O(NlogN)
int findKthLargest(vector<int> & nums, int k) { sort(nums.begin(), nums.end()); return nums[k-1];}
方法2: 类似快排的分治思想 O(N)
int partition(vector<int> &nums, int left, int right) { int l = left, r = right; int pivot = nums[l]; while (l < r) { while (l < r && nums[r] <= pivot) r--; nums[l] = nums[l]; while (l < r && nums[l] >= pivot) l++; nums[r] = nums[l]; } nums[l] = pivot; return l; }int findKthLargest_QuickSort(vector<int> nums, int k) { int left = 0, right = nums.size() - 1; while (true) { int pos = partition(nums, left, right); if (pos == k - 1) return nums[pos]; if (pos > k - 1) right = pos; else left = pos; }}
方法3:堆排序思想,调整堆k次
void max_heapify(vector<int> &nums, int p, int heap_size) { int child = 2 * p + 1; int p_val = nums[p]; while (child < heap_size) { if (child + 1 < heap_size && nums[child] < nums[child+1]) { child += 1; } if (nums[child] > p_val) { nums[p] = nums[child] ; p = child; child = 2 * p + 1; } else break; } nums[p] = p_val;}void build_max_heap(vector<int> &nums, int heap_size) { int heap_size = nums.size(); for (int i = (heap_size >> 1) -1; i >= 0; i--) { max_heapify(nums, i, heap_size); }}int findKthLargest_Heap(vector<int> nums, int k) { build_max_heap(nums, heap_size); for (int i = 0; i < k; i++) { swap(nums[0], nums[heap_size-1]); heap_size --; max_heapify(nums, 0); } return nums[heap_size];}
方法4: 利用STL的priority_queue
int findKthLargest(vector<int>& nums, int k) { priority_queue<int> pq(nums.begin(), nums.end()); for (int i = 0; i < k - 1; i++) { pq.pop(); } return pq.top(); }
2. 无序数组找K最频繁(要求时间复杂度小于O(NlogN))
因为k最大可以等于n,所以在最坏情况下需要统计所有数字的出现次数。那么这个问题就分成了两个部分:
因为最后只需要返回k个数字,所以可以维护一个大小为k的小根堆。当新的数字出现的次数大于堆中最小的次数时,对堆进行更新。时间复杂度是O(n log k)。- 统计所有不同的数字出现的次数
- 找出出现次数前k大的数字
// hash + priority_queuevector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int,int> map; for(int num : nums){ map[num]++; } vector<int> res; // pair<first, second>: first is frequency, second is number priority_queue<pair<int,int>> pq; for(auto it = map.begin(); it != map.end(); it++){ pq.push(make_pair(it->second, it->first)); if(pq.size() > (int)map.size() - k){ res.push_back(pq.top().second); pq.pop(); } } return res; }
可以采用桶排序做进一步优化,该算法复杂度只和需要排序的数字的大小有关。可以用一个数组bucket记录每个数字出现的次数,每次把数字丢到相应编号的桶中,然后从后往前穷举每一个桶,取出其中的元素直到取满k个。时间复杂度是O(n)。
vector<int> topKFrequent(vector<int>& nums, int k) { vector<int> res; if (!nums.size()) return res; unordered_map<int, int> cnt; for (auto num : nums) cnt[num]++; vector<vector<int>> bucket(nums.size() + 1); for (auto kv : cnt) { bucket[kv.second].push_back(kv.first); } for (int i = bucket.size() - 1; i >= 0; --i) { for (int j = 0; j < bucket[i].size(); ++j){ res.push_back(bucket[i][j]); if (res.size() == k) return res; } } return res; }
0 0
- topK问题
- topK问题
- topk 问题
- TopK问题
- topK问题
- TopK问题
- TopK问题
- topK问题之我见
- 求topK问题
- 一道TOPK问题
- 漫谈topK 问题
- 经典topK问题
- topk问题C++实现
- TopK问题详解
- make_heap topk 问题
- TopK问题 Java代码
- 求TopK问题
- Spark TopK问题解法
- Android开发之RatingBar
- 代码世界中的Lambda
- 结合Apache和Tomcat实现集群和负载均衡
- 看懂UML类图(节选)
- 广告相关概念整理
- TopK问题
- hdu1233 还是畅通工程 最小生成树 Prim算法堆优化
- Spring4+Mybatis不能读取 properties
- JavaFilter类
- 在yii中使用分页
- php使用openssl来实现非对称加密
- 【线性规划与网络流24题 24】骑士共存问题
- [李景山php]每天laravel-20161129|BelongsToMany.php-1
- 职场人士如何减压-如何缓解职场强迫症