Loading

剑指Offer41.数据流中的中位数

题目链接:剑指 Offer 41. 数据流中的中位数

思路:极大堆、极小堆。因为输入是数据流不是数组,说明输入的数据是不确定的。一般来说先排序,然后返回中间数,但每查询一次就要排序,时间复杂度较高。所以想能不能每次查询都可以直接获取到中间数,而不是对输入的数据排序取中间数。那么,我们就把输入的数据分为两堆,每次输入数据都只会进入两个堆中的一个,而两个堆的中间分界线就是中位数。

代码:

class MedianFinder {
    PriorityQueue<Integer> maxHeap, minHeap;

    /** initialize your data structure here. */
    public MedianFinder() {
        maxHeap = new PriorityQueue<>((a, b) -> b - a);
        minHeap = new PriorityQueue<>((a, b) -> a - b);
    }
    
    public void addNum(int num) {
        if(maxHeap.isEmpty()){
            maxHeap.offer(num);
            return ;
        }
        if(num <= maxHeap.peek()){
            maxHeap.offer(num);
        }else{
            minHeap.offer(num);
        }
        this.adjust();
    }
    
    public double findMedian() {
        return maxHeap.size()==minHeap.size()?(double)(maxHeap.peek()+minHeap.peek())/2:maxHeap.size() > minHeap.size()?maxHeap.peek():minHeap.peek();
    }

    private void adjust(){
        if(maxHeap.size() - minHeap.size() < 2 && maxHeap.size() - minHeap.size() > -2){
            return ;
        }
        if(maxHeap.size() - minHeap.size() >= 2){
            minHeap.offer(maxHeap.poll());
        }
        if(maxHeap.size() - minHeap.size() <= -2){
            maxHeap.offer(minHeap.poll());
        }
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */
执行用时:75 ms, 在所有 Java 提交中击败了92.29%的用户
内存消耗:49.8 MB, 在所有 Java 提交中击败了40.09%的用户
posted @ 2020-12-13 12:06  yoyuLiu  阅读(84)  评论(0编辑  收藏  举报