数据流中的中位数

第六十二题:数据流中的中位数

    • 题目描述
    • 思路
          • 具体图解如下
          • 具体实现代码如下


题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。


思路

根据题意可知当数据为 :
奇数:中位数为(排序后的中间的数)
偶数:中位数为(排序后的中间的两个数的平均值)
由于本题的特殊性(数据流:数据是源源不断的添加)由此我们不能得到已经排好序的数组(甚至自己实现排序也不好做)
建立两个堆(大根堆 小根堆)
1.)保证大根堆中时刻都是较小的一半 堆顶为最大值
2.)保证小根堆中时刻都是较大的一半 堆顶为最小值
3.)新增元素比较与两个堆顶值的关系(大小) 选择进入哪个堆
4.)任何一个size比另外一个大 2 时 进行调整


具体图解如下

数据流中的中位数_第1张图片
数据流中的中位数_第2张图片


具体实现代码如下
// 数据流中的中位数
public class Solution {

    // 小顶堆
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    // 大顶堆
    PriorityQueue<Integer> maxHeap = new PriorityQueue<>(11, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2.compareTo(o1);
        }
    });

    public void addNumber(Integer num){
        // 第一次添加数值
        if (this.maxHeap.isEmpty()){
            this.maxHeap.add(num);
            return;
        }
        // 当前数值比大顶堆的堆顶值小,将该数添加到大顶堆
        if (this.maxHeap.peek() >= num){
            this.maxHeap.add(num);
        }else {
            // 第一次添加数值
            if (this.minHeap.isEmpty()){
                this.minHeap.add(num);
                return;
            }
            // 当前数值比小顶堆的堆顶值小,将该数添加到大顶堆
            if (this.minHeap.peek() > num){
                this.maxHeap.add(num);
            }else {
                this.minHeap.add(num);
            }
        }
        this.modifyTwoHeapsSize();
    }

    public Double getMedian(){
        Integer maxHeapSize = this.maxHeap.size();
        Integer minHeapSize = this.minHeap.size();
        if (maxHeapSize + minHeapSize == 0){
            return null;
        }
        Integer maxHeapHead = this.maxHeap.peek();
        Integer minHeapHead = this.minHeap.peek();
        // 判断奇偶
        if (((maxHeapSize + minHeapSize) & 1) == 0){
            return (double) ((maxHeapHead + minHeapHead) / 2.0);
        }else if (maxHeapSize > minHeapSize){
            return (double) maxHeapHead;
        }else {
            return (double) minHeapHead;
        }
    }

    private void modifyTwoHeapsSize(){
        if (this.maxHeap.size() == this.minHeap.size() + 2){
            this.minHeap.add(this.maxHeap.poll());
        }
        if (this.minHeap.size() == this.maxHeap.size() + 2){
            this.maxHeap.add(this.minHeap.poll());
        }
    }
}

NowCoder(Online Coding, Please Click)

你可能感兴趣的:(剑指offer)