剑指 Offer 41 数据流中的中位数

这篇博客介绍了一种利用两个堆(一个最小堆minHeap和一个最大堆maxHeap)来实现实时添加数字并查找中位数的方法。通过在每次添加元素后调整堆,确保minHeap和maxHeap分别维护序列的较大和较小区间。当需要查找中位数时,根据两个堆的大小关系返回相应元素。这种方法的时间复杂度为O(logn),空间复杂度为O(n)。
摘要由CSDN通过智能技术生成

题目:数据不断的进入,要求实现addNum()和findMedian()两个函数。来进行数字的添加和中位数的查找。

public void addNum(int num)
public double findMedian()

思路:1.先说一下基本的思路:
可以对目前的数据进行排序,如使用快速排序O(nlogn),然后直接返回中间的那个数O(1)。
2.
一:维护较大元素区间的minHeap和一个维护较小元素区间的maxHeap
二:怎么维持?用什么条件判断?(addNum的实现内容)
三:返回中位数时用什么条件判断?

用一个维护较大元素区间的minHeap和一个维护较小元素区间的maxHeap来做,时间复杂度为O(logn)(堆的操作时间复杂度为O(logn)),空间复杂度为O(n)。

为什么一个(维护较大元素)minHeap和一个(维护较小元素)maxHeap可以实现查找中位数?

因为维护较大元素的minHeap的堆顶元素和维护较小元素的maxHeap堆顶元素分别对应一个有序序列中间的2个数或1个数。就相当于用这两个不同的堆模拟了一个有序序列从中间分为两半。这两个堆的元素从一个方向看正好是一个有序序列。这样就可以获得中位数。

如何维持维护较大元素区间的minHeap和维护较小元素区间的maxHeap?

首先把一个元素加入maxHeap,然后经过堆调整后,把maxHeap堆顶元素加入到minHeap,这样就把大的元素(maxHeap出来的是最大值)慢慢地放到了minHeap中,就维持较大区间了。反过来也是,这样就可以维持。

注意:
1.其实第一下加到哪个heap都行
2.返回两堆顶的和/2.0,一定要/2.0化为double。size不相等时总体元素数为单数,返回minHeap堆顶元素。
3.用minHeap和maxHeap的size()来判断

	/*
    先说一下有什么基本思路
    思路:用两个堆,一个大顶堆,一个小顶堆。
    大顶堆维护着较小的区间序列,小顶堆维护着较大的区间序列。
    如果minHeap和maxHeap的总和是奇数,那么中位数就是minHeap的堆顶(第一步先往maxHeap放)
    如果minHeap和maxHeap的总和是偶数,那么中位数就是minHeap和maxHeap各自堆顶的平均数。

    怎么维护各自一直是较大或较小区间呢?
    每加进堆一个元素,就把该堆的堆顶元素放到另一堆里,
    这样就能保证较大的区间序列就一直是较大的,较小的区间序列就一直是较小的。
     */

    PriorityQueue<Integer> minHeap = null;
    PriorityQueue<Integer> maxHeap = null;

    public MedianFinder() {
	    //优先队列PriorityQueue的底层是堆实现的,默认是最小堆
        minHeap = new PriorityQueue<>();
        //用lamda表达式来做,来构建最大堆
        maxHeap = new PriorityQueue<>((x,y) -> (y-x));
    }

    public void addNum(int num) {
        //先加入maxHeap,maxHeap为维护较小区间的大顶堆。应该也可以第一下先加minHeap
        if(minHeap.size() == maxHeap.size()){
            maxHeap.add(num);
            minHeap.add(maxHeap.poll());
        }else{
            //加过maxHeap了,这次加minHeap
            minHeap.add(num);
            maxHeap.add(minHeap.poll());
        }
    }

    public double findMedian() {
        if(minHeap.isEmpty() && maxHeap.isEmpty()) return -999;
        //返回值为double,所以要/2.0,化为浮点数
        return minHeap.size() != maxHeap.size() ? minHeap.peek() : (minHeap.peek()+maxHeap.peek())/2.0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值