剑指offer打卡|数据流中的中位数

题目描述

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

代码

创建优先级队列维护大顶堆和小顶堆两个堆,并且小顶堆的值都大于大顶堆的值,2个堆个数的差值小于等于1,所以当插入个数为奇数时:大顶堆个数就比小顶堆多1,中位数就是大顶堆堆头;当插入个数为偶数时,使大顶堆个数跟小顶堆个数一样,中位数就是 2个堆堆头平均数。

注意:小顶堆的数一直比大顶堆的数要大

import java.util.*;
public class Solution {
    //默认实现的是最小堆,数据从小到大排列
    private PriorityQueue<Integer> low=new PriorityQueue<Integer>();
    //最大堆要通过比较器Comparator实现
    private PriorityQueue<Integer> high=new PriorityQueue<>((o1,o2)->o2-o1);
    //(1) 写成return o1.compareTo(o2) 或者 return o1-o2表示升序
    //(2) 写成return o2.compareTo(o1) 或者 return o2-o1表示降序);
    //当前读入的数据个数
    int count=0;
    //读取数据流
    public void Insert(Integer num) {
        count++;
        if((count%2)!=0){
            //奇数的时候插入大顶堆
            low.add(num);
            high.add(low.poll());
        }else{
         /* N 为偶数的情况下插入到右半边。
         * 因为右半边元素都要大于左半边,但是新插入的元素不一定比左半边元素来的大,
         * 因此需要先将元素插入左半边,然后利用左半边为大顶堆的特点,取出堆顶元素即为最大元素,此时插入右半边 */
            high.add(num);
            low.add(high.poll());
        }
    }
    //获取当前读取数据的中位数
    public Double GetMedian() {
        if(count==0){
            return null;
        }
        if((count%2)!=0){
            //奇数时中位数是大顶堆的头
            return Double.valueOf(high.peek());
        }else{
            //偶数时中位数是小顶堆的头和大顶堆的头的和除2
            return Double.valueOf((high.peek()+low.peek()))/2;
        }
    }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值