問題:如何在無限大的資料流中隨機選取k個資料,保證當前遍歷過的i個元素中每乙個元素被選中的概率均為 k/i?從而對於n個元素,每個元素被選中的概率均為 k/n。
解:對於前k個元素,我們直接選中放入乙個虛擬的蓄水池中,對於第 k+1 個元素,我們用 k/(k+1) 的概率選中它,一旦選中了,就隨機替換掉蓄水池中的某乙個元素,這樣前 k 個被選中的元素在第 k+1 個元素到來時依然被選中的概率即為它不被替換掉的概率:
p = 1*(1-被替換掉的概率q)
q = k/(k+1) * 1/k #即前k個元素中某個元素被替換時,某個被替換的概率為 1/k
這樣 p = k/(k+1)
對於當前被遍歷到的第 k+1 個元素,它被放到蓄水池中的概率就是它被選中的概率,即 k/(k+1),因為只要它被選中,就一定會替換掉蓄水池中的某個元素而留在水池中;
同理,對於第 m +1 個元素(m>>k)的到來,前m個元素被選中的概率均為 k/m,進行第 m+1 次選擇時,前 m 個元素依然保留在蓄水池中的概率為:
p = k/m * = k/(m+1) #即 p=之前在水池中的概率*(1 - 被第m+1個元素替換替換掉的概率 )
或者p = k/m * = k/(m+1) #即 p=之前在水池中的概率*(第m+1個元素未被選中的概率 + 第m+1個元素被選中但是替換了其他k-1個元素的概率)
**實現時,遍歷到第 i 個元素時(i>k),可以直接生成乙個 (1,i)之間的隨機數 r ,如果 r<=k,那麼就讓當前第 i 個元素替換蓄水池中的第 r 個元素即可,把選中和替換哪乙個元素融合為一步了,概率是不變的,即被選中的概率為 k/i,蓄水池中的 k 個元素每乙個被替換的概率也為 1/k 。
init : a reservoir with the size: k
for i= k+1 to n
r=random(1, i);
if( r < k)
swap the r th value and i th value
end for
參考:
演算法 蓄水池抽樣
例題 有乙個機器按自然數序列的方式吐出球,1號球,2號球.現有乙個袋子,袋子裡最多只能裝下k個球,並且除袋子以外沒有更多的空間,球扔掉不能放回。設計一種選擇方式,使得當機器吐出第n號球時,袋子中的球數是k個,同時可以保證從1號球到n號球中的每乙個被選中進袋子的概率都是k n。具體例子 有乙個只能裝下...
蓄水池抽樣演算法
給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 蓄水池抽樣演算法 該演算法是針對從乙個序列中隨機抽取不重複的k個數,保證每個數被抽取到的概率為k n這個問題...
蓄水池抽樣演算法
題目 要求從n個元素中隨機的抽取k個元素,其中n無法確定 解法 首先選擇n中的前k個數加入 蓄水池 中,然後從第k 1個數開始,以k k i i 1,2,3.的概率選擇這個數,然後在蓄水池中隨機選擇乙個數,並將其替換,n個元素遍歷完畢後,蓄水池中的k個數就是隨機選擇的。證明 這裡即需要證明每個數出現...