63 数据流的中位数

本文介绍了一种在数据流中实时计算中位数的方法,通过使用两个堆(大顶堆和小顶堆)来平衡数据,确保在任意时刻都能快速获取到中位数。详细解释了插入新数据和获取中位数的具体步骤。

题目要求:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

 

用两个堆保存数据,保持两个堆的数据保持平衡(元素个数相差不超过1)

大顶堆存放的数据要比小顶堆的数据小

当两个堆中元素为奇数个,将新加入元素加入到大顶堆,如果要加入的数据,比小顶堆的最小元素大,先将该元素插入小顶堆,然后将小顶堆的最小元素插入到大顶堆。

当两个堆中元素为偶数个,将新加入元素加入到小顶堆,如果要加入的数据,比大顶堆的最大元素小,先将该元素插入大顶堆,然后将大顶堆的最大元素插入到小顶堆。

 

 1 import java.util.Comparator;
 2 import java.util.PriorityQueue;
 3 public class Solution {
 4     //全局变量count用来统计加入了多少个数
 5     int count=0;
 6     PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
 7     PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11, new Comparator<Integer>() {
 8         @Override
 9         public int compare(Integer o1, Integer o2) {
10             //PriorityQueue默认是小顶堆,实现大顶堆,需要反转默认排序器
11             return o2.compareTo(o1);
12         }
13     });
14     public void Insert(Integer num) {
15     count++;
16           //每次插入小顶堆的是当前大顶堆中最大的数
17           //每次插入大顶堆的是当前小顶堆中最小的数
18           //这样保证小顶堆中的数永远大于等于大顶堆中的数
19           //中位数就可以方便地从两者的根结点中获取了
20     if( (count & 1) == 0) { // 判断偶数的高效写法
21             if (!maxHeap.isEmpty() && num < maxHeap.peek()) {
22                 maxHeap.offer(num);
23                 num = maxHeap.poll();
24             }
25             minHeap.offer(num);
26         } else { //奇数情况
27             if (!minHeap.isEmpty() && num > minHeap.peek()) {
28                 minHeap.offer(num);
29                 num = minHeap.poll();
30             }
31             maxHeap.offer(num);
32         }
33     }
34     public Double GetMedian() {   
35         if(count==0)
36             throw new RuntimeException("no available number!");
37         double result;
38        //总数为奇数时,大顶堆堆顶就是中位数
39        if((count&1)==1)
40             result=maxHeap.peek();
41         else
42             result=(minHeap.peek()+maxHeap.peek())/2.0;
43         return result;
44     }
45 }

 

转载于:https://www.cnblogs.com/shareidea94/p/11242969.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值