如何得到乙個資料流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用insert()方法讀取資料流,使用getmedian()方法獲取當前讀取資料的中位數。
資料流中的資料需要用合適的容器存放。
方法1:用陣列
用陣列存放是比較直接的方法,將新資料插入乙個陣列的時間複雜度是o(1),從中找中位數可以用partition的方法(參考:陣列中出現次數超過一半的數字),時間複雜度是o(n)。但是陣列有個問題是必須事先指定長度。
方法2:用堆
資料被中位數分為兩半,用乙個最大堆和乙個最小堆,各存放一半的數字,且最大堆中數字都小於最小堆中數字。則最大堆存放的是中位數左邊的數字,最小堆中存放的是中位數右邊的數字。
具體實現的時候,為了保證兩個堆中數字平均分配,可以在資料總數為偶數時將新資料放進最小堆中,資料總數為寄數時將新資料放進最大堆中。但是要保證新資料放進去之後最大堆中的數字都比最小堆中數字小,所以在將新資料放進最小堆之前,先要判斷新資料是不是比最大堆中資料都大,最大堆堆頂的資料是最大的資料,要是新資料比堆頂資料還大,就可以直接放入最小堆,要是新資料比堆頂資料小,那就先把新資料放進最大堆,然後把新的最大堆中的最大數取出來放進最小堆。將新資料放入最大堆之前也要進行類似的判斷。
注意:我們採用vector容器和stl中的函式push_heap,pop_heap實現堆,用less和greater函式實現最大最小堆。
每次插入元素後呼叫push_heap(maxheap.begin(),maxheap.end(),less())對插入的元素做堆排序,預設使用less表示將最大元素放在第乙個位置。如果要刪除堆頂元素,先呼叫pop_heap(maxheap.begin(),maxheap.end(),less()),將堆頂元素與end前的元素(即最後乙個元素)交換,然後將除了最後乙個元素之外的元素重新進行堆排序。
ac**
class solution
minheap.push_back(num);
push_heap(minheap.begin(),minheap.end(),greater());
}else
maxheap.push_back(num);
push_heap(maxheap.begin(),maxheap.end(),less());}}
double getmedian()
else
return (minheap[0]+maxheap[0])/2.0;
}private:
vectormaxheap;
vectorminheap;
};
劍指offer 資料流中的中位數
題目描述 如何得到乙個資料流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。實現 public class getmediannum listnode in new listnod...
劍指Offer 資料流中的中位數
題目描述 如何得到乙個資料流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。思路整理 這個題目要解出來很簡單,但是這裡有乙個比較好的思路 用最大和最小堆來實現,就像乙個沙漏一樣,上...
劍指offer 資料流中的中位數
題意 每次輸入乙個數字,輸出當前資料流的中位數。我也給出了main函式,含義就是類似的就是main函式中的例子。include 記住這句話,能夠包含所有標頭檔案 using namespace std class solution if p.top num else if p.size 2 q.si...