数据流中的中位数

241 阅读1分钟

题目

剑指 Offer 41. 数据流中的中位数 - 力扣(LeetCode)

思路

维护一个大根堆和一个小根堆(两个堆大小相差不超过1),其中大根堆存储较小的那半部分数据,小根堆存储较大的那半部分数据,因此大根堆的堆顶和小根堆的堆顶可以代表中位数的取值。

需要注意:

  • 在两个堆大小不一样的时候,元素多的那个堆的堆顶是中位数,否则是两个堆的堆顶的平均值。
  • 规定小根堆大于等于大根堆,在插入新元素的时候,如果两个堆一样大,则插入小根堆,否则插入大根堆。
  • 为了保证数据在合适的位置,若插入大根堆,则先将其插入到小根堆,然后再将小根堆的堆顶元素放到大根堆里,反之也是。

代码

class MedianFinder {

    // 使用大根堆和小根堆,堆顶是取中位数的地方
    PriorityQueue<Integer> maxHeap;
    PriorityQueue<Integer> minHeap;

    /** initialize your data structure here. */
    public MedianFinder() {
        maxHeap = new PriorityQueue<Integer>((x, y) -> (y - x));
        minHeap = new PriorityQueue<Integer>();
    }
    
    public void addNum(int num) {
        if(maxHeap.size() != minHeap.size()){
            // 加到max里
            minHeap.add(num);
            maxHeap.add(minHeap.poll());
        }else{
            // 加到min里
            maxHeap.add(num);
            minHeap.add(maxHeap.poll());
        }
    }   
    
    public double findMedian() {
        if(maxHeap.size() != minHeap.size()){
            return minHeap.peek();
        }else{
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        }
    }
}