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

例如,

[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
进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

链接:https://leetcode-cn.com/problems/find-median-from-data-stream
思路都放在代码里了。结合代码看味道更好

class MedianFinder {

    //基本思想 建立两个堆 分别存放一半的数据
    //1.保证大根堆的堆顶永远小于小根堆顶
    //2.保证两个堆的数据差只为1
    public PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
    public PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>  (){ //大顶堆,容量11
        @Override
        public int compare(Integer i1,Integer i2){
            return i2-i1;
        }
    });

    /** initialize your data structure here. */
    public MedianFinder() {
        
    }
    
   public void addNum(int num) {

        if(maxHeap.isEmpty())//如果大根堆为空 则把数字放入大根堆
        {
            maxHeap.offer(num);
            return;
        }
        //如果两个堆的大小一样
        //第一中情况 两个堆的数量一样 保证大根堆的头 比小根堆的头要小 且相差为1
        if(maxHeap.size()==minHeap.size())
        {
            //比小根堆头大 放小根堆;比小根堆头小 放大根堆 (这边其实也能和大根堆比都能过)
            if(num>minHeap.peek())
            {
                minHeap.offer(num);
            }
            else
            {
                maxHeap.offer(num);
            }
        }
        else if(minHeap.size()>maxHeap.size())
        {//如果小根堆多一些,那就和小根堆的数字比 这时候可以在笔记本上画一下
        //例子为6 10 11 12/7
            if(num>minHeap.peek())//12>10 需要把10弹出到大根
            {
                maxHeap.offer(minHeap.poll());
                minHeap.offer(num);
            }
            else//7<10 直接去大根  我就是这边的代码写错了 调了很久
            {
                maxHeap.offer(num);
            }
        }
        else if(minHeap.size()<maxHeap.size())
        {//如果大根堆多一些 直接和大根堆比 实例 4,3/10
            if(num>maxHeap.peek())
            {
                minHeap.offer(num);//10大于4 直接去小根那边
            }
            else//3《4 要先把4送到小根 然后把三放进去
            {
                minHeap.offer(maxHeap.poll());
                maxHeap.offer(num);
            }
        }

    }
    
    public double findMedian() {
        double temp;
        if(maxHeap.size()==minHeap.size())
        {
            return (maxHeap.peek()+minHeap.peek())/2.0;//记得这边转一下啊float
        }
        else if(maxHeap.size()>minHeap.size())
        {
            return maxHeap.peek();
        }
        else
        {
            return minHeap.peek();
        }


        }
    
}

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