資料流中的中位數(劍指offer/C++)
阿新 • • 發佈:2018-12-13
題目描述
如何得到一個數據流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取資料流,使用GetMedian()方法獲取當前讀取資料的中位數。
室友大晚上回來和我分享這道題解題思路,他給出的方案是藉助最大堆和最小堆資料結構解題,這一塊我應用不是很熟,我首先想到的就是用map容器對資料流中的數值進行計數,再用利用一個計數器找出中位數。
這裡需要提一下是map的底層實現是紅黑樹(插入資料時,已經自動完成排序(基於key)),保證了一個穩定的動態操作時間,查詢、插入、刪除都是O(logN),最壞和平均都是。但是在利用計數器查詢的時候,時間複雜度是O(N)。演算法細節見程式碼:
class Solution { public: map<int, int> mp; int count = 0; void Insert(int num) { count++; if (mp.find(num) == mp.end()) { mp[num] = 1; } else { mp[num]++; } } double GetMedian() { if (count % 2 != 0) { int tmp = 0; map<int, int>::iterator it = mp.begin(); while (it != mp.end()) { tmp += it->second; if (tmp > count / 2) { return 1.0*it->first; } it++; } } else { int tmp = 0; map<int, int>::iterator it = mp.begin(); while (it != mp.end()) { tmp += it->second; if (tmp > (count - 1) / 2 ) { if (tmp > count / 2) { return 1.0*it->first; } else { return 1.0*(it->first + (++it)->first)/2.0; } } it++; } } return 0; } };