程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 68. 蓄水池抽樣(Reservoir Sampling)

68. 蓄水池抽樣(Reservoir Sampling)

編輯:C++入門知識

[本文鏈接]

http://www.cnblogs.com/hellogiser/p/reservoir-sampling.html

問題起源於編程珠玑Column 12中的題目10,其描述如下:

How could you select one of n objects at random, where you see the objects sequentially but you do not know the value of n beforehand? For concreteness, how would you read a text file, and select and print one random line, when you don’t know the number of lines in advance?

(1)在不知道文件總行數n的情況下,如何從文件中隨機的抽取一行?

解:先選擇第一個行,並使用1/2的概率選擇第二個行,使用1/3的概率選擇第三行,使用1/i的概率選擇第i行,以此類推。在過程結束時,每個對像被選中的概率都是1/n。

用P(i)表示處於第i行時第i行被選中的概率。

P(1)=1

P(2)=1/2

P(3)=1/3

則選擇第3行的時候,對於第1行來講選中的概率=第一行被選中概率*第二行沒被選中*第3行沒被選中概率。

p(1)all=P(1)*(1-P(2))(1-P(3))=1/3

p(2)all=P(2)*(1-P(3))=1/3

p(3)all=P(3)=1/3

證明:

1最終被選中的概率:1被選中的概率*2沒有被選中的概率*3沒有被選中的概率*…*n沒有被選中的概率

p(1)all=1*(1-1/2)(1-1/3)*…*(1-1/n)=1/n

m最終被選中的概率:m被選中的概率*m+1沒有被選中的概率*m+2沒有被選中的概率*…*n沒有被選中的概率(1<=m<n)

p(m)all=1/m*[1-1/(m+1)][1-1/(m+2)]*…*[1-1/n]=1/n

(2)對其進行擴展,即如何從未知或者很大樣本空間隨機地取k個數?

給你一個長度為N的鏈表。N很大,但你不知道N有多大。你的任務是從這N個元素中隨機取出k個元素。你只能遍歷這個鏈表一次。你的算法必須保證取出的元素恰好有k個,且它們是完全隨機的(出現概率均等)。

解:先選中前k個, 從第k+1個元素到最後一個元素為止, 以k/i (i=k+1, k+2,...,N) 的概率選中第i個元素,並且隨機替換掉一個原先選中的元素, 這樣遍歷一次得到k個元素, 可以保證完全隨機選取。

證明:

n最終被選中的概率: n被選中的概率*[(n+1)沒有被選中的概率+(n+1)被選中概率*n沒被替換的概率]

p(n)all=k/n*[(1-k/(n+1))+k/(n+1)*(1-1/k)]=k/(n+1)

【參考】

http://www.cnblogs.com/ttltry-air/archive/2012/08/10/2632215.html

[本文鏈接]

http://www.cnblogs.com/hellogiser/p/reservoir-sampling.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved