Reservoir sampling(水塘抽樣)

2021-07-17 00:16:18 字數 2256 閱讀 1589

題目1:

給出乙個資料流,這個資料流的長度很大或者未知。並且對該資料流中資料只能訪問一次。請寫出乙個隨機選擇演算法,使得資料流中所有資料被選中的概率相等。

對於複雜問題一定要學會歸納總結,即從小例子入手,然後分析,得出結論,然後在證明。不然遇到乙個抽象問題,不舉例感覺這個問題,直接解還是比較難的。

對於此問題的難處就是資料流的長度未知,如果已知,so easy。現在進行歸納總結:

1) 長度為1,只有乙個資料,直接返回即可,此資料被返回的概率為1.

2)長度為2,當讀取第一資料時,我們發現並不是最後乙個資料,我們不能直接返回,因為資料流還沒結束,繼續讀取,到第二資料的時候,發現已經結束。所以現在的問題就是等概率返回其中的乙個,顯然概率為0.5。所以此時我們可以生成乙個0到1的隨機數p,如果p小於0.5,返回第二個,如果大於0.5,返回第乙個。顯然此時兩個資料被返回的概率是一樣的。

3)長度為3,我們可以事先分析得到,為了滿足題意,需要保證每個資料返回的概率都是1/3。接下來分析資料流,首先讀取第乙個資料,然後在讀取第二個資料,此時可以按2)處理,保留乙個資料,每個資料顯然為1/2。此時讀取第三個資料,發現到尾部了,為了滿足題意,此時需要一1/3的概率決定是否取此資料。現在分析前兩個數是否也是以1/3的概率返回,如果是則總體都滿足。資料1和資料2同時留下的概率為:1/2 *(1-1/3)= 1/3。1/2只在資料1和資料2pk時,能留下的概率,1-1/3指資料3不被留下的概率。所以,對長度為3的資料流,在讀取第三個資料時,我們可以生成乙個0到1的隨機數p,如果p小於1/3,返回第三個資料,否則,返回前面兩個pk留下的資料。

由上面的分析,我們可以得出結論,在取第n個資料的時候,我們生成乙個0到1的隨機數p,如果p小於1/n,保留第n個數。大於1/n,繼續保留前面的數。直到資料流結束,返回此數。

下面用數學歸納法證明此結論。

1)當n=1時,第乙個元素以1/1的概率返回,符合條件。

2)假設當n=k時成立,即每個元素都以1/k的概率返回,先證明n=k+1時,是否成立。

對於最後乙個元素顯然以1/k+1的概率返回,符合條件,對於前k個資料,被返回的概率為1/k * (1- 1/k+1)=1/k+1,滿足題意。

綜上所述,結論成立。

題目2

對於題目1的要就變為,最後返回的結果長度為k,這就是水塘抽樣

顯然有了對題目1的理解,我們可以直接替換結論,只需把上面的1/n變為k/n即可。

在取第n個資料的時候,我們生成乙個0到1的隨機數p,如果p小於k/n,替換池中任意乙個為第n個數。大於k/n,繼續保留前面的數。直到資料流結束,返回此k個數。但是為了保證計算機計算分數額準確性,一般是生成乙個0到n的隨機數,跟k相比,道理是一樣的。

可以以同樣的方法證明之。

(1)初始情況k<=n,出現在水庫中的k個元素的出現概率都是一致的,都是1

(2)第一步。第一步就是指,處理第k+1個元素的情況。分兩種情況:元素全部都沒有被替換;其中某個元素被第k+1個元素替換掉。

我們先看情況2:第k+1個元素被選中的概率是k/(k+1)(根據公式k/i),所以這個新元素在水庫中出現的概率就一定是k/(k+1)(不管它替換掉哪個元素,反正肯定它是以這個概率出現在水庫中)。下面來看水庫中剩餘的元素出現的概率,也就是1-p(這個元素被替換掉的概率)。水庫中任意乙個元素被替換掉的概率是:(k/k+1)*(1/k)=1/(k+1),意即首先要第k+1個元素被選中,然後自己在集合的k個元素中被選中。那它出現的概率就是1-1/(k+1)=k/(k+1)。可以看出來,舊元素和新元素出現的概率是相等的。

情況1:當元素全部都沒有替換掉的時候,每個元素的出現概率肯定是一樣的,這很顯然。但具體是多少呢?就是1-p(第k+1個元素被選中)=1-k/(k+1)=1/(k+1)。

(3)歸納法:重複上面的過程,只要證明第i步到第i+1步,所有元素出現的概率是相等的即可。

偽**如下:

//stream代表資料流  

//reservoir代表返回長度為k的池塘

//從stream中取前k個放入reservoir;

for ( int i = 1; i < k; i++)

reservoir[i] = stream[i];

for (i = k; stream != null; i++) {

p = random(0, i);

if (p < k) reservoir[p] = stream[i];

return reservoir;

水塘抽樣(Reservoir sampling)

水塘抽樣 reservoir sampling 題目 給出乙個資料流,這個資料流的長度很大或者未知。並且對該資料流中的資料只能訪問一次。請寫出乙個隨機選擇演算法,使得資料流中所有資料被選中的概率相等。這個問題的擴充套件就是 如何從未知或者很大樣本空間隨機的取k個數?或者說,資料流長度為n行,要隨機抽...

Shuffle an Array 水塘抽樣

隨機性問題 水塘抽樣演算法可保證每個樣本被抽到的概率相等 使用場景 從包含n個專案的集合s中選取k個樣本,其中n為一很大或未知的數量,尤其適用於不能把所有n個專案都存放到主記憶體的情況 拿起第i張牌時,只從它前面的牌隨機選出j,或從它後面的牌隨機選出j交換即可 1 class solution 67...

水塘抽樣演算法

作用 水塘抽樣演算法是一種抽樣演算法,對於乙個很大的集合,抽取的樣本值能夠保證隨機.特點 其複雜度並不很高o n 並且能夠很大程度地節省記憶體.很多大公司的面試題都考察過這個演算法,以谷歌為例,有一道關於水塘抽樣的例題 我有乙個長度為n的鍊錶,n的值非常大,我不清楚n的確切值.我怎樣能寫乙個盡可能高...