版权声明:本文为博主NJU_ChopinXBP原创文章,发表于CSDN,仅供交流学习使用,转载请私信或评论联系,未经博主允许不得转载。感谢您的评论与点赞。 https://blog.csdn.net/qq_20304723/article/details/88073762
2019.3.2 《剑指Offer》从零单刷个人笔记整理(66题全)目录传送门
这道题有技巧,想要实时获得中位数,需要最大堆+最小堆的数据结构,将所有大于等于中位数的元素放在最小堆,将所有小于中位数的元素放在最大堆。
对数据总数进行计数,要保证:
1. 在总数为奇数时,直接弹出最小堆堆顶即为中位数,即此时最小堆元素比最大堆元素多1个。
2.在总数为偶数时,弹出最小堆堆顶和最大堆堆顶取平均即为中位数,即此时最大堆元素和最小堆元素相等。
因此,对于每次数据流中的新元素:
1.若该元素是第奇数个元素,元素先经过最大堆过滤,将最大堆堆顶元素(最小值)放入最小堆。
2.若该元素是第偶数个元素,元素先经过最小堆过滤,将最小堆堆顶元素(最大值)放入最大堆。
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
Java实现:
/**
*
* @author ChopinXBP
* 如何得到一个数据流中的中位数?
* 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
* 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
* 我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
*
*/
import java.util.Comparator;
import java.util.PriorityQueue;
public class GetMedianofStream_62 {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
private PriorityQueue <Integer> minheap = new PriorityQueue <>();
private PriorityQueue<Integer> maxheap = new PriorityQueue<>(15, new Comparator<Integer>() {
@Override
//反转为最大堆
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
private int count = 0;
//所有大于等于中位数的数据放在最小堆,所有小于中位数的数据放在最大堆
public void Insert(Integer num) {
count++;
//当数据总数为奇数时,数据先进入最大堆筛选,最大堆顶部元素进入最小堆
if((count & 0x01) == 1) {
maxheap.add(num);
minheap.add(maxheap.poll());
}
//当数据总数为偶数时,数据先进入最小堆筛选,最小堆顶部元素进入最大堆
else {
minheap.add(num);
maxheap.add(minheap.poll());
}
}
public Double GetMedian() {
//数据为偶数时,最小堆和最大堆顶部为中位数
if((count & 0x01) == 0) {
return new Double((minheap.peek() + maxheap.peek())) / 2;
}
//数据为奇数时,最小堆顶部为中位数
else {
return new Double(minheap.peek());
}
}
}
C++实现示例:
class Solution {
priority_queue<int, vector<int>, less<int> > p;
priority_queue<int, vector<int>, greater<int> > q;
public:
void Insert(int num){
if(p.empty() || num <= p.top()) p.push(num);
else q.push(num);
if(p.size() == q.size() + 2) q.push(p.top()), p.pop();
if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();
}
double GetMedian(){
return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
}
};
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#