數據流中的中位數

若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。咱們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。ide

解題思路:使用最大堆和最小堆,若是插入個數是奇數,則是中間的數,若是是偶數,則是中間兩數之和的一半,好比1,2,3,4,5,6,那麼中位數就是中間兩位之和的一半,如今問題就轉換爲怎麼定位這兩個數,因此能夠使用最大堆和最小堆,根據堆的性質,最大堆的堆頂元素最大,最小堆的堆頂元素最小,最大堆用於保存前半部分的數(1,2,3),最小堆用於保存後半部分的數(4,5,6),當插入的個數是奇數時,返回最大堆的堆頂便是中位數,若是是偶數,則是最大堆的堆頂和最小堆的堆頂之和的一半,;此時最大堆的堆頂元素爲3,最小堆的堆頂爲4,因此中位數爲二者之和的一半(3+4)/ 2.0 = 3.5。code

public class Solution {
    private int cnt = 0;
    private PriorityQueue<Integer> low = new PriorityQueue<>();
    private PriorityQueue<Integer> high = new PriorityQueue<>(   //默認是最小堆,最大堆須要重寫方法
    new Comparator<Integer>(){
        public int compare(Integer o1, Integer o2){
            return o2.compareTo(o1);
        }
    });
    public void Insert(Integer num) {
        ++cnt;
         if((cnt & 1) == 1){
            if(!low.isEmpty() && num > low.peek()){   //當最小堆不爲空,而且待插入的數大於最小堆堆頂時彈出堆頂
                 low.offer(num);
                 num = low.poll();
            }
             high.offer(num);
             }
        else{
            if(!high.isEmpty() && num < high.peek()){  //當最大堆不爲空,而且待插入的數小於最大堆堆頂時彈出
                high.offer(num);
                num = high.poll();
            }
            low.offer(num);
        }
    }

    public Double GetMedian() {
        if((cnt & 1) == 1){   //插入個數爲奇數
            return high.peek() * 1.0;
        }else{      //插入個數爲偶數
            return (high.peek() + low.peek()) / 2.0;
}
}

}排序

相關文章
相關標籤/搜索