蓄水池抽樣
今天又在“待字閨中”上看到將蓄水池抽樣的題,想起一年多之前小光找工作的時候考過我這個。這裏做個備忘。
轉自:https://www.guokr.com/blog/745588/
題目要求:
從個元素中隨機抽取個元素,但的個數無法事先確定。
在實際應用中,往往會遇到很大數據流的情況。因此,我們無法先保存整個數據流然後再從中選取,而是期望有一種將數據流遍歷一遍就得到所選取的元素,並且保證得到的元素是隨機的算法。
蓄水池抽樣算法:
- 先選取n個元素中的前k個元素,保存在集合A中;
- 從第 j (k+1 <= j <= n) 個元素開始,每次先以概率選擇是否讓第 j 個元素留下。若第 j 個元素存活,則從A中隨機選擇一個元素並用該元素 j 替換它;否則直接淘汰該元素 j ;
- 重複1和2,直到結束。最後集合 A 中剩下的就是保證隨機抽取的 k 個元素。
蓄水池抽樣算法正確性證明:
爲了證明該算法的正確性,我們要保證算法結束後,原n個元素每一個最後存活下來的概率都是 k/n(因爲從 n 個元素中隨機抽取k個元素,每個元素被抽中的概率都是k/n)。形式化地,我們要證明的結論是:在算法的第 i(0<= i <= n-k) 輪,前 k+i個元素每一個存活下來的概率都是 k/(k+i)。
----------------------------------------
利用數學歸納法:
- 當 i=0 時,結論顯然成立。
- 當 0< i <= n-k 時,根據算法,元素 k+i 存活的概率爲 k/(k+i)。而對於元素 l (1<= l < k+i),有兩種情況會使其存活下來:要麼元素 k+i 直接被淘汰;要麼元素k+i 留下,但是沒有替換掉元素 l 。由歸納假設, i-1 時結論成立,故元素 l 存活的概率爲,得證。
----------------------------------------
值得一提的是,在實際中,常常需要通過一次遍歷,從大量的個元素中隨機選取一個。這其實是蓄水池抽樣在時的特例。