排序(中级)
Q1 最小的k个数
感觉比较快的两个思路:
- 快速排序: 已知快排每一次调用Partition函数会将数列划分为大于小于基准数的两个序列,则我们可以在快排某次调用Partition函数时判断是否是K+1的位置,若是则停止,此时前k个为最小k个数
- 推排序,小根堆,每次取top,然后与堆底交换,调整。但是手撕堆排序最好从a[1]开始存数,因为此时2 * i 和 2 * i + 1(不越界)正好为孩子节点
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> array;
int len = arr.size();
priority_queue<int,vector<int>,greater<int> >q;
for(int i=0;i<len;i++) q.push(arr[i]);
for(int i=0;i<k;i++)
{
array.push_back(q.top());
q.pop();
}
return array;
}
};
Q2 数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
class MedianFinder {
public:
// 最大堆,存储左边一半的数据,堆顶为最大值
priority_queue<int, vector<int>, less<int>> maxHeap;
// 最小堆, 存储右边一半的数据,堆顶为最小值
priority_queue<int, vector<int>, greater<int>> minHeap;
MedianFinder() {
}
// 维持堆数据平衡,并保证左边堆的最大值小于或等于右边堆的最小值
void addNum(int num) {
if (maxHeap.size() == minHeap.size()) {
minHeap.push(num);
int top = minHeap.top();
minHeap.pop();
maxHeap.push(top);
} else {
maxHeap.push(num);
int top = maxHeap.top();
maxHeap.pop();
minHeap.push(top);
}
}
double findMedian() {
if (maxHeap.size() == minHeap.size()) {
return (maxHeap.top()+minHeap.top())/2.0;
} else {
return maxHeap.top()*1.0;
}
}
};