中位數是有序列表中間的數。如果列表長度是偶數,中位數則是中間兩個數的平均值。
例如,
[2,3,4] 的中位數是 3
[2,3] 的中位數是 (2 + 3) / 2 = 2.5
設計乙個支援以下兩種操作的資料結構:
void addnum(int num) - 從資料流中新增乙個整數到資料結構中。
double findmedian() - 返回目前所有元素的中位數。
示例:addnum(1)
addnum(2)
findmedian() -> 1.5
addnum(3)
findmedian() -> 2
高階:
如果資料流中所有整數都在 0 到 100 範圍內,你將如何優化你的演算法?
如果資料流中 99% 的整數都在 0 到 100 範圍內,你將如何優化你的演算法?
思路:
建立2個堆,分別為大頂堆,小頂堆。其中,大頂堆用於管理中位數之前的數,小頂堆用於管理中位數之後的數。
在資料壓入時,得考慮:
(1)第1個資料,首先壓入大頂堆。
(2)第2個資料,得判斷該資料與大頂堆堆頂資料的大小關係,若大於,則直接壓入小頂堆。若小於,則將該數與大頂堆堆頂資料交換,再壓入小頂堆。
(3)第3個及以後的資料,首先判斷該數與大頂堆堆頂、小頂堆堆頂之間的關係,再進行資料交換和判斷插入的堆,具體看**。
資料壓入完後,判斷大頂堆資料數目與小頂堆資料數目的大小,若相等,即資料流的個數為偶數,取兩個堆頂元素,作和除以2即可得中位數。若大頂堆資料數目大於小頂堆資料數目,即資料流的個數為奇數,取大頂堆堆頂元素,即為中位數。
**:
class
medianfinder
void
addnum
(int num)
//第2次壓入資料,先判斷要壓入的資料與大頂堆頂部之間的大小
if(big_q.
size()
==1&& small_q.
size()
==0)else
return;}
//第3次以及後面押入資料
tmp_big=big_q.
top();
tmp_small=small_q.
top();
if(num
//判斷num與大頂堆頂部的大小關係
else
if(num>tmp_small)
//判斷num與小頂堆頂部的大小關係
if(big_q.
size()
==small_q.
size()
)//判斷num要壓入的頂堆
else
}double
findmedian()
if(big_q.
size()
==small_q.
size()
)else}}
;
簡化**:
class
medianfinder
void
addnum
(int num)
}double
findmedian()
};
複雜度:
時間複雜度:o(5
⋅logn
)+o(
1)≈o
(logn
)o(5⋅logn)+
o(1)
≈o(logn)
。最壞情況下,從頂部有三個堆插入和兩個堆刪除。每乙個都需要花費 o(l
ogn)
o(logn)
o(logn
) 時間。
找到平均值需要持續的 o(1) 時間,因為可以直接訪問堆的頂部。
空間複雜度:o(n
)o(n)
o(n)
用於在容器中儲存輸入的線性空間。
結果:
資料流中的中位數python 資料流中的中位數
python用的自己實現的最大和最小堆的class,getmedian需要加個引數,否則python版會報錯。coding utf 8 最小堆 class minheap def init self self.minheap def len self return len self.minheap ...
資料流中的演算法
資料流統計功能上線後,為51nod提公升使用者體驗做出了很大的貢獻。但是新問題隨之而來,夾克老爺還想知道在乙個視窗內,訪問次數最多使用者 即視窗內的眾數 如果有多個眾數,取使用者id最小的乙個。視窗的意思是乙個固定長度的區間!input 第一行為整數n,k。1 n 5 10 6,1 k 1000 n...
TCP互動資料流 成塊資料流
tcp資料流分類 基於tcp的各類解決方案,可以根據資料吞吐量來大致分成兩大類 1 互動資料型別,例如telnet,ssh,這種型別的協議在大多數情況下只是做小流量的資料交換,比如說按一下鍵盤,回顯一些文字等等。2 資料成塊型別,例如ftp,這種型別的協議要求tcp能盡量的運載資料,把資料的吞吐量做...