Leetcode--Java--295. 数据流的中位数

题目描述

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

样例描述

示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2

思路

队顶堆 (大根堆 + 小根堆)

  1. 预先设定如果是奇数个,让左边大根堆个数比右边小根堆个数多一。中位数就左边堆的堆顶。偶数就是两个堆的堆顶元素求平均数。
    在这里插入图片描述
  2. 对于当前元素t,如果小于左边堆顶元素x,就插入到左边堆,否则插入到右边堆。在插入过程中要保证,左边堆的数目最多比右边堆的数目多一。 需要调整的话就移动左边堆堆顶的元素。 因为它是最大的,同时能保证整体满足左边小于右边的这个性质。

代码

class MedianFinder {
    
    
    //左边大根堆和右边小根堆
    PriorityQueue<Integer> leftMax;
    PriorityQueue<Integer> rightMin;
    public MedianFinder() {
    
    
     leftMax = new PriorityQueue<>((a, b) -> b - a);
     rightMin = new PriorityQueue<>((a, b) -> a - b);
    }
    
    public void addNum(int num) {
    
    
       //如果左边空,或者比左边小,就插入到左边
       if (leftMax.isEmpty() || num <= leftMax.peek()) {
    
    
           leftMax.offer(num);
           //判断是否需要调整,  左边最多比右边多一
           if (leftMax.size() > rightMin.size() + 1) {
    
    
               //将左边堆顶元素插入到右边
               rightMin.offer(leftMax.poll());
           }
       } else {
    
    
           rightMin.offer(num);
           //同样判断是否满足右边不大于左边
           if (rightMin.size() > leftMax.size()) {
    
    
               leftMax.offer(rightMin.poll());
           }
       }
    }
    
    public double findMedian() {
    
    
        //如果左边堆数大于右边,说明是奇数  注意是double除以2.0
       if (leftMax.size() > rightMin.size()) return leftMax.peek();
       else return (leftMax.peek() + rightMin.peek()) / 2.0;
    }
}

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

猜你喜欢

转载自blog.csdn.net/Sherlock_Obama/article/details/121651184
今日推荐