如何隨機從n個物件中(這n個物件是按序排列的,但是在此之前你是不知道n的值的)隨機選擇乙個物件?
具體來說,如何在實現不知道文字檔案行數的情況下讀取該檔案,從中隨機選擇並輸出一行?
這是《程式設計珠璣》中的乙個習題,如果我們知道n的值,那麼問題就可以簡單的用乙個大隨機數rand()%n得到乙個確切的隨機位置,那麼該位置的物件就是所求的物件,選中的概率是1/n。
現在並不知道n的值,
我們總是選擇第乙個物件,以1/2的概率選擇第二個,以1/3的概率選擇第三個,以此類推,以1/m的概率選擇第m個物件。當該過程結束時,每乙個物件具有相同的選中概率,即1/n。
針對讀取文字檔案的例子,我們總選擇第1行,並以概率1/2選擇第2行,以1/3的概率選擇第3行,
依此類推,在這一過程結束時,每一行的選中概率是相等的,都是1/n,其中n是檔案的總行數。
給出偽**:1
2
3
4
5
i=
0
while
more input lines
with probaility
1
/++i
choice=
this
input line
print choice
這個問題可以抽象到更普遍的情況,就是蓄水池抽樣問題。
從n個元素中隨機抽取k個元素,但n的個數無法事先確定。
在實際應用中,往往會遇到很大資料流的情況。因此,我們無法先儲存整個資料流然後再從中選取,而是期望有一種將資料流遍歷一遍就得到所選取的元素,並且保證得到的元素是隨機的演算法。
上面的問題就是k=1的的蓄水池抽樣問題。
看一下解決蓄水池抽樣問題的演算法:
1.先選取n個元素中的前k個元素,儲存在集合a中;
2.即從第k+1個元素開始,
每次先以k/(k+1)概率選擇該元素,以k/(k+2)的概率選擇第k+2個元素,
以此類推,以k/m的概率選擇第j個物件(k+1<=m<=n)。
如果第m個元素被選中,則從a中隨機選擇乙個元素並用元素m替換它;否則直接淘汰元素m;
最終每個物件被選中的概率均為k/n。
證明如下:
給定乙個長度為n且沒有重複元素的陣列arr和乙個整數m,實現函式等概率隨機列印arr中的m個數。
首先在0~n-1中隨機得到乙個位置a,列印arr[a],然後把arr[a]和陣列最後位置的arr[n-1]交換;
然後在0~n-2中隨機得到乙個位置b,然後把arr[b]和陣列最後位置的arr[n-2]交換,
arr:,n-1,
依此類推,直到列印m個數即可。
蓄水池抽樣演算法應用
如何隨機從n個物件中 這n個物件是按序排列的,但是在此之前你是不知道n的值的 隨機選擇乙個物件?具體來說,如何在實現不知道文字檔案行數的情況下讀取該檔案,從中隨機選擇並輸出一行?這是 程式設計珠璣 中的乙個習題,如果我們知道n的值,那麼問題就可以簡單的用乙個大隨機數rand n得到乙個確切的隨機位置...
演算法 蓄水池抽樣
例題 有乙個機器按自然數序列的方式吐出球,1號球,2號球.現有乙個袋子,袋子裡最多只能裝下k個球,並且除袋子以外沒有更多的空間,球扔掉不能放回。設計一種選擇方式,使得當機器吐出第n號球時,袋子中的球數是k個,同時可以保證從1號球到n號球中的每乙個被選中進袋子的概率都是k n。具體例子 有乙個只能裝下...
蓄水池抽樣演算法
給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 蓄水池抽樣演算法 該演算法是針對從乙個序列中隨機抽取不重複的k個數,保證每個數被抽取到的概率為k n這個問題...