剑指 Offer 41. 数据流中的中位数(困难)

思路:

使用2个优先队列,一个存储较大的一半,另一个存储较小的一半

如果是奇数,就返回小顶堆(存储较大一半)的堆顶元素

如果是偶数,就返回两堆堆顶元素/2.0的值

 

代码:

class MedianFinder {
	
	Queue<Integer> A,B;
    /** initialize your data structure here. */
    public MedianFinder() {
		A=new PriorityQueue<>();//小顶堆(存储较大的一半)
		B=new PriorityQueue<>((a,b)->(b-a));//大顶堆(存储较小的一半)
    }
    
    public void addNum(int num) {
		if(A.size()==B.size()){
			//向A中添加元素,必须先将此元素添加到B中确认是否属于较小的一半
			B.add(num);
			A.add(B.poll());
		}
		else{
			//向B中添加元素,必须先将此元素添加到A中确认是否属于较大的一方
			A.add(num);
			B.add(A.poll());
		}
    }
    
    public double findMedian() {
		if(A.size()==B.size()){
			//偶数,取中间2数之和/2
			//因为返回的是double类型,所以要/2.0
			return (A.peek()+B.peek())/2.0;
		}
		else{
			//奇数,取A的顶端元素
			return A.peek();
		}
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

 

分解:

1)小顶堆:堆顶是整个堆中最小的元素,升序,PriorityQueue默认是升序(小顶堆)

大顶堆:堆顶是整个堆中最大的元素,降序,要重写比较器

 

2)整个过程:

    i)如果A、B的元素个数不相等,就往A中添加元素。但这个元素可能是属于较小一半的,所以要将此数加到B中,再从B的堆顶弹出较大的数,加入到A中

    ii)如果A、B的元素个数相等,就往B中添加元素。但这个歌元素可能是属于较大一半的,所以要将此数加到A中,再从A的堆顶弹出较小的数,加入到B中

   

求中位数:

    iii)如果A、B总和为偶数,则分别弹出A、B的堆顶元素,相加后/2.0

    iv)如果A、B总和为奇数,返回A的堆顶元素即可

 

3)因为中位数要求是double类型,所以要/2.0而不是2.否则答案不正确

 

复杂度分析:

时间复杂度:O(logN)

i)查找中位数:O(1),只查找堆顶元素即可

ii)堆的插入,弹出:O(logN)

 

空间复杂度:O(N) A、B最多同时存储N个元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值