[問題]在不知道檔案總行數的情況下,如何從檔案中隨機的抽取一行?
[解析]首先想到的是我們做過類似的題目嗎?當然,在知道檔案行數的情況下,我們可以很容易的用c執行庫的rand函式隨機的獲得乙個行數,從而隨機的取出一行,但是,當前的情況是不知道行數,這樣如何求呢?我們需要乙個概念來幫助我們做出猜想,來使得對每一行取出的概率相等,也即隨機。這個概念即
蓄水池抽樣(reservoir sampling)
。有了這個概念,我們便有了這樣乙個解決方案:定義取出的行號為choice,第一次直接以第一行作為取出行 choice ,而後第二次以二分之一概率決定是否用第二行替換 choice ,第三次以三分之一的概率決定是否以第三行替換 choice ……,以此類推,可用偽**描述如下:
i = 0這種方法的巧妙之處在於成功的構造出了一種方式使得最後可以證明對每一行的取出概率都為1/n(其中n為當前掃瞄到的檔案行數),換句話說對每一行取出的概率均相等,也即完成了隨機的選取。while more input lines
with probability 1.0/++i
choice = this input line
print choice
證明如下:
回顧這個問題,我們可以對其進行擴充套件,即如何從未知或者很大樣本空間隨機地取k個數?
模擬下即可得到答案,即先把前k個數放入蓄水池,對第k+1,我們以k/(k+1)概率決定是否要把它換入蓄水池,換入時隨機的選取乙個作為替換項,這樣一直做下去,對於任意的樣本空間n,對每個數的選取概率都為k/n。也就是說對每個數選取概率相等。
偽**:
init : a reservoir with the size: k證明如下:for i= k+1 to n
m=random(1, i);
if( m < k)
swap the mth value and ith value
end for
蓄水池抽樣問題是一類問題,在這裡總結一下,並
由衷的感嘆這種方法之巧妙,不過對於這種思想產生的源頭還是發覺不夠,如果能夠知道為什麼以及怎麼樣想到這個解決方法的,定會更加有意義。
蓄水池抽樣問題
題目 微軟電面問到的問題,前面提了一大堆背景,最後歸結為乙個問題,如何在連續的網路流量中,等概率隨機抽取1個資料報。分析 參加電面時,還沒看過蓄水池抽樣問題,後來回來一搜,這就是典型的蓄水池抽樣問題,不過當時自己也想到了一種解法,使用乙個變數儲存資料報,從1到i個資料報,每次遇到第i個資料報,以1 ...
蓄水池抽樣問題
為分析使用者行為,系統常需儲存使用者的一些query,但因query非常多,故系統不能全存,設系統每天只存m個query,現設計乙個演算法,對使用者請求的query進行隨機選擇m個,請給乙個方案,使得每個query被抽中的概率相等,並分析之,注意 不到最後一刻,並不知使用者的總請求量。蓄水池抽樣問題...
蓄水池抽樣問題
一般有兩種問題,一種是從乙個未知的序列中隨機選擇乙個,因此其概率為1 m,m代表當前元素 當從乙個未知的序列中挑選k個元素或者從乙個已知序列長度為n n非常大 中挑選k個元素,使每個元素被挑選的概率均等,稱之為蓄水池取樣問題。具體思路是 首先挑選k個元素,放入蓄水池中 然後從第k 1個元素開始,使得...