剑指OfferJZ63:数据流中的中位数-java版

本文介绍了如何利用Java通过大顶堆和小顶堆数据结构实现实时计算数据流中的中位数。当数据流包含奇数或偶数元素时,通过调整堆的操作来保证中位数的正确性。重点讲解了插入和获取中位数的方法,以及堆顶操作在不同情况下的运用。
摘要由CSDN通过智能技术生成

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

采用大顶堆和小顶堆分别维护中位数的左边区间的数和右边区间的数

如果数据流有偶数个数值,那么中位数为(左区间的最大值+右区间的最小值)/2
如果数据流有奇数个数值,那么中位数为(左区间的最大值 | 右区间的最小值)(这个可以自定义,哪个区间多一个数就取哪个区间)
那么采用堆:
取左区间的最大值就相当于取大顶堆的堆顶
取右区间的最大值就相当于取小顶堆的堆顶

import java.util.PriorityQueue;
public class Solution {
//设置两个优先队列(队列:先进先出;优先级队列中,数据按关键词有序排列,插入新数据的时候,会自动插入到合适的位置保证队列有序,默认排序为升序)
    private PriorityQueue<Integer> queue1=new PriorityQueue<>(((o1,o2)->(o2-o1)));//构造大顶堆:中位数的左区间
    private PriorityQueue<Integer> queue2=new PriorityQueue<>();//构造小顶堆:中位数的右区间(优先队列默认构造的是小堆顶,因为每次取出的队顶元素都是最小的,所以也可以new PriorityQueue<>(((o1,o2)->(o1-o2)));)
    private int sum=0;//标记数据流中个数


    public void Insert(Integer num) {
        //读取数据流
        if(sum%2==0){
            //当两个堆的元素个数一样时,此时新增一个元素,放入大顶堆(左区间)(这样自定义:到时候中位数就取大顶堆堆顶)
            queue1.add(num);//大顶堆
        }else{
            queue2.add(num);//小顶堆
        }
        //如果出现大顶堆的堆顶大于小顶堆的堆顶的情况,就将两堆顶互换位置
        if(!queue2.isEmpty() && queue1.peek()>queue2.peek()){
            //peek:查询队顶元素
            // poll:删除一个元素,并返回删除的元素
            assert !queue1.isEmpty();//设置assert !queue1.isEmpty();和!queue2.isEmpty()防止空指针报异常
            int temp1=queue1.poll();
            int temp2=queue2.poll();
            queue1.add(temp2);
            queue2.add(temp1);
        }
        sum++;
    }

    public Double GetMedian() {
        //获取当前读取数据的中位数
        if(sum%2==1){
            //是奇数,中位数为:大顶堆堆顶
            return (double)queue1.peek();
        }else{
            //是偶数,中位数为:(大顶堆堆顶+小顶堆堆顶)/2
            return (double)(queue1.peek()+queue2.peek())/2.0;
        }
    }
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李莲花*

多谢多谢,来自一名大学生的感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值