給定乙個長度很長的資料流,在處理完成之前不知道其具體長度,如何在遍歷一遍資料流的情況下,隨機地抽出m個不重複的資料。
key words:
長度很長,遍歷完之前不可知;
o(n)複雜度;
等概率地抽出m個數,每個數被抽中的概率為m/n。
如果接收的資料量小於m,直接放入蓄水池reservoir
如果接收的數量大於m,假設是第i個資料,i>=m
,則在[1,i]
中隨機選擇乙個數,假設為x
,如果x重複步驟2直到讀取完資料流
vector<如何保證每個數被抽到的概率為mint>
reservoir
(m);
//蓄水池中的m個元素
for(
int i =
0; i < m; i++
)for
(int i = m; i < datastream.
size()
; i++
)
n\frac
nm。
第i
個接收到的資料最後能夠留在蓄水池中的概率=第i
個資料進入過蓄水池的概率*之後第i個資料不被替換的概率(第i+1到第n次處理資料都不會被替換)。
if(i <= m)
,第i
個資料肯定可以進入過蓄水池,概率為1,我們還需要求出,第i
個數後續一直不會被替換的概率;
if(i <= m)
,第i
個資料後續不被替換的概率怎麼求?
我們先求第i
個資料被替換的概率。
從第m +1
m+1m+
1個數開始,第i
個數就有可能被替換啦,從m+1
m+1m+
1個數中抽乙個數,抽到的數小於等於m
mm的概率為mm+
1\frac
m+1m
,m
mm個數中抽到的恰好是i
ii的概率為1
m\frac
m1 ,所以第i
ii個數被替換的概率為mm+
1∗1m
=1m+
1\frac*\frac=\frac
m+1m∗
m1=
m+11
.那麼第i
ii個數不被替換的概率為1−1
m+1=
mm+1
1-\frac=\frac
1−m+11
=m+
1m。
對於第m+2
m+2m+
2個數,第i
ii個數不被替換的概率為m+1
m+
2\frac
m+2m+1
。以此類推,從第m+1
m+1m+
1一直到第n
nn個數,第i
ii個數一直不會被替換的概率為:mm+
1∗m+
1m+2
∗...
∗n−1
n=mn
\frac*\frac*...*\frac=\frac
m+1m∗
m+2m
+1∗
...∗
nn−1
=nm
。綜合1)2),當i
<=m
i<=m
i<=m
時,第i個資料進入過蓄水池的概率*之後第i個資料不被替換的概率 = 1∗m
n=mn
1*\frac=\frac
1∗nm=
nm。
if(i>m)
,第i
個數進入蓄水池的概率為m
i\frac
im,從第i+1
i+1i+
1個數開始,第i
個數可能被替換出蓄水池,根據前面的結果,從第i+1
一直到第n
個數都不會替換第i
個數的概率為:ii+
1∗i+
1i+2
∗...
∗n−1
n=in
\frac*\frac*...*\frac=\frac
i+1i∗
i+2i
+1∗
...∗
nn−1
=ni
。於是第i
個數留在蓄水池中的概率為mi∗
in=m
n\frac*\frac=\frac
im∗ni
=nm
。綜上:蓄水池演算法可以保證每個數被抽到的概率為m
n\frac
nm。
蓄水池 抽樣
蓄水池抽樣問題描述的是,在乙個無窮盡的樣本中,要求隨即抽取一些樣本,這些樣本被抽取到的概率必須保持一致。乙個蓄水池就可以理解為無窮大的樣本空間。解決方案就是蓄水庫抽樣 reservoid sampling 主要思想就是保持乙個集合,作為蓄水池,依次遍歷所有資料的時候以一定概率替換這個蓄水池中的數字。...
蓄水池抽樣
題目 要求從n個元素中隨機的抽取k個元素,其中n無法確定 解法 首先選擇n中的前k個數加入 蓄水池 中,然後從第k 1個數開始,以k k i i 1,2,3.的概率選擇這個數,然後在蓄水池中隨機選擇乙個數,並將其替換,n個元素遍歷完畢後,蓄水池中的k個數就是隨機選擇的。證明 這裡即需要證明每個數出現...
蓄水池抽樣
給定乙個資料流,資料流長度n很大,且n直到處理完所有資料之前都不可知,請問如何在只遍歷一遍資料 o n 的情況下,能夠隨機選取出m個不重複的資料。這個場景強調了3件事 資料流長度n很大且不可知,所以不能一次性存入記憶體。時間複雜度為o n 隨機選取m個數,每個數被選中的概率為m n。蓄水池抽樣演算法...