若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。咱們使用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;
} }
}排序