题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
题意理解:动态的求平均
例如,传入的数据为:[5,2,3,4,1,6,7,0,8],那么按照要求,输出是"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
PriorityQueue(优先队列)
实际上是一个堆(不指定Comparator时默认为最小堆)
优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator
进行排序
此队列的头 是按指定排序方式确定的最小 元素,队列获取操作 poll
、remove
、peek
访问处于队列头的元素。
解题思路
查看别人的解析,大多采用大顶堆小顶堆(第一次接触顶堆)
ps1:小顶堆存较大的数,从小到大的顺序排序*
PriorityQueue
默认为小顶堆
private
PriorityQueue<Integer> minHeap =
new
PriorityQueue<Integer>();
ps2:大顶堆存较小的数,从大到小的顺序排序*(需重写compare方法)
private
PriorityQueue<Integer> maxHeap =
new
PriorityQueue<Integer>(
new
Comparator<Integer>() {
@Override
public
int
compare(Integer o1, Integer o2) {
return
o2 - o1;
}
分奇偶的目的:保证这两个堆是平衡的(即这两个堆的数量相等或相差1),保证中位数就可以通过这两个堆的堆顶元素获得
step1:
⭐当数目为奇数的时候,将这个值插入小顶堆中;
step2:
⭐将小顶堆中根节点(即最小值)插入到大顶堆中;
step3:⭐当数目为偶数的时候,将这个值插入大顶堆中;
step4:⭐将大顶堆中根节点(即最大值)插入到小顶堆中;
step5:⭐取中位数的时候,如果当前个数为偶数,取小两堆根结点的平均值;如果当前个数为奇数,取小顶堆的根节点
明确核心:1,分奇偶插入 2,插入后将堆顶元素移到另一个堆中
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
//小顶堆
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
//大顶堆
private PriorityQueue <Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//记录奇数偶数
int count=0;
public void Insert(Integer num) {
if(count%2==0){
maxHeap.add(num);
int temp = maxHeap.poll();
minHeap.add(temp);
}else{
minHeap.add(num);
int temp = minHeap.poll();
maxHeap.add(temp);
}
count++;
}
public Double GetMedian() {
double result;
if (count%2==0){
result =(minHeap.peek()+maxHeap.peek())/2.0;
}else {
result = minHeap.peek();
}
return result;
}
}}
链接:https://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1?f=discussion
来源:牛客网