[剑指 Offer 40]. 最小的 k 个数
Posted Debroon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[剑指 Offer 40]. 最小的 k 个数相关的知识,希望对你有一定的参考价值。
剑指 Offer 40. 最小的 k 个数
题目
函数原型
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
}
};
快排 partition 思想
完整解析:快速排序之种种。
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if(arr.empty() || k == 0) return {};
vector<int> ans;
selectK(arr, 0, arr.size()-1, k-1); // 第 k 小数字对应索引是 k-1
for (int i = 0; i < k; ++i)
ans.push_back(arr[i]);
return ans;
}
// 封装 partition
int partition(vector<int>& arr, int l, int r){
// 生成 [l, r] 之间的随机索引
int p = rand() % (r - l + 1) + l;
swap(arr[l], arr[p]);
// arr[l+1...i-1] <= v; arr[j+1...r] >= v
int i = l + 1, j = r;
while(true) {
while(i <= j && arr[i] < arr[l])
i ++;
while(j >= i && arr[j] > arr[l])
j --;
if(i >= j) break;
swap(arr[i], arr[j]);
i ++;
j --;
}
swap(arr[l], arr[j]);
return j;
}
void swap( int &a, int &b ){
int tmp = a;
a = b;
b = tmp;
}
// 封装 selectK
int selectK(vector<int>& arr, int l, int r, int k){
int p = partition(arr, l, r);
if(k == p) return arr[p]; // k == p,直接返回
if(k < p) return selectK(arr, l, p - 1, k); // k < p,在左边找
return selectK(arr, p + 1, r, k); // k > p,在右边找
}
};
优先队列
只需要使用一个优先队列维护当前看到最小的 k 个元素。
对于每一个新元素,如果比这 k 个最小元素中最大的还小,就替换。
实现优先队列的数据结构是,最大堆。
用最大堆维护当前看到的最小 k 个元素,不停的拿这 k 个最小元素中最大值和新元素比较。
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> vec(k, 0);
if (k == 0) // 排除 0 的情况
return vec;
priority_queue<int> Q;
for (int i = 0; i < k; ++i)
Q.push(arr[i]);
for (int i = k; i < (int)arr.size(); ++i)
if (Q.top() > arr[i]) {
Q.pop();
Q.push(arr[i]);
}
for (int i = 0; i < k; ++i) {
vec[i] = Q.top();
Q.pop();
}
return vec;
}
};
快排与优先队列的比较
快排中位数思路:
- 时间: O ( n ) O(n) O(n)
- 空间: O ( 1 ) O(1) O(1)
优先队列:
- 时间: O ( n l o g k ) O(n~logk) O(n logk)
- 空间: O ( k ) O(k) O(k)
发现无论时间、空间,快排中位数思路都比优先队列优秀。
但优先队列有一个最大优势,不需要一次性知道所有数据。
-
我是游戏服务器开发,之前有很多系统需要做查询排名前N的需求。比如战斗力排名前十的玩家,我的做法是有个全局排序的过程,但是这样在玩家很多时,效率会越来越低。当时与同事以及领导商量也没有好的解决方案,于是就妥协采用了全局实时排序。
-
同时我在团队内普及了这个方案,使得很多类似需求的系统,比如竞技场排名前十、消费前十等等都得到了提升。
以上是关于[剑指 Offer 40]. 最小的 k 个数的主要内容,如果未能解决你的问题,请参考以下文章