劍指offer:資料流中的中位數(java)
阿新 • • 發佈:2018-12-11
/** * 題目: * 如何得到一個數據流中的中位數?如果從資料流中讀出奇數個數值, * 那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值, * 那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取資料流, * 使用GetMedian()方法獲取當前讀取資料的中位數。 * 解題思路: * 用兩個推儲存資料,保持兩個堆的資料保持平衡(元素個數相差不超過1) * 大頂堆存放的資料要比小頂堆的資料小 * 當兩個推中元素為偶數個,將新加入元素加入到大頂堆,如果要加入的資料,比小頂堆的最小元素大, * 先將該元素插入小頂堆,然後將小頂堆的最小元素插入到大頂堆。 * 當兩個推中元素為奇數個,將新加入元素加入到小頂堆,如果要加入的資料,比大頂堆的最大元素小, * 先將該元素插入大頂堆,然後將大頂堆的最大元素插入到小頂堆。 * 當元素個數是奇數個時,大頂堆元素比小頂堆多一個,中位數即為大頂堆的堆頂元素 * 若為偶數,則中位數是大小頂堆的堆頂元素之和除2 */ import java.util.TreeSet; public class P214_GetMedian { TreeSet<Integer> max = new TreeSet<Integer>(); //大頂堆,用於存放前面一半的元素 TreeSet<Integer> min = new TreeSet<Integer>(); //小頂堆,用於存放後面一般的元素 public void Insert(Integer num) { if (((max.size()+min.size()) & 1) == 0) { //偶數個 if (min.size() > 0 && num > min.first()) { min.add(num); num = min.first(); min.remove(num); } max.add(num); }else { if (max.size() > 0 && num < max.last()) { max.add(num); num = max.last(); max.remove(num); } min.add(num); } } public Double GetMedian() { int size = max.size() + min.size(); if (size == 0) { return 0.0; } if ((size & 1) == 0) { return (max.last() + min.first()) / 2.0; }else { return (double)max.last(); } } }