优先队列:剑指 Offer 41. 数据流中的中位数
原题地址:https://leetcode.cn/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/
题解
参考官方题解
我们创建两个优先队列,其中minQue为小于等于中位数的队列(降序),maxQue为大于中位数的队列(升序),如对于数据流[1,2,3,4,5]而言
- minQue={3,2,1}
- maxQue={4,5}
由于中位数位置的特殊性,我们可以知道
- 当数据个数为奇数时,minQue的长度为maxQue的长度+1,且中位数等于minQue的队头
- 当数据个数为偶数时,minQue的长度等于maxQue的长度,且中位数等于minQue的队头与maxQue的队头的平均数
在加入新元素a时,需要平衡两个优先队列,考虑两种情况:
当原先数据个数为奇数时:
此时加入元素后数据个数为偶数,加入后minQue和maxQue的长度必须相等,设b=minQue.remove()
- 此时我们获得了a、b和两个长度相同的队列,比较a和b的大小,将较大值加入maxQue,较小值加入minQue即可
当原先数据个数为偶数时:
此时加入元素后数据个数为奇数,加入后minQue.size()=maxQue.size()+1,设b=minQue.remove(),c=maxQue.remove()
- 此时我们获得了a、b、c和两个长度相同的队列,比较a、b、c的大小,将较大值加入maxQue,较小的两个值加入minQue即可
时间复杂度:O(1)
空间复杂度:O(N)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class MedianFinder { PriorityQueue<Integer> maxQue=new PriorityQueue<>((Integer a,Integer b)->a-b); PriorityQueue<Integer> minQue=new PriorityQueue<>((Integer a,Integer b)->b-a); public MedianFinder() { maxQue=new PriorityQueue<>((Integer a,Integer b)->a-b); minQue=new PriorityQueue<>((Integer a,Integer b)->b-a); }
public void addNum(int num) { int b,c,min,max; if(minQue.size()==0){ minQue.add(num); } else if(maxQue.size()==minQue.size()){ b=maxQue.remove(); c=minQue.remove(); max=Math.max(num,Math.max(b,c)); min=Math.min(num,Math.min(b,c)); minQue.add(min); minQue.add(num +b+c-max-min); maxQue.add(max); }else if(maxQue.size()==minQue.size()-1){ b=minQue.remove(); max=Math.max(num,b); min=Math.min(num,b); minQue.add(min); maxQue.add(max); } }
public double findMedian() { if(maxQue.size()==minQue.size()){ return (double)(maxQue.peek()+minQue.peek())/2; }else{ return (double)minQue.peek(); } } }
|