題目:
從n個元素中隨機抽取k個元素,n的個數不確定,要求保證每個數字被抽中的概率相等。
解讀:這種應用的場景一般是資料流的情況下,由於資料只能被讀取一次,而且資料量很大,並不能全部儲存,因此資料量n是無法在抽樣開始時確定的;但又要保證概率相等。
解決:解決方案就是蓄水池抽樣。主要思想就是保持乙個集合(這個集合最終的數字就是被抽中的數字)。依次遍歷所有資料的時候以一定的概率替換掉這個蓄水池中的數字。
其偽**為:
init : a reservoir with the size: k //初始化蓄水池為前k個數
for i= k+1 to n
m=random(1, i);
if( m < k)
swap the mth value and ith value
end for
程式的開始就是把前k個元素都放到水庫中,然後對之後的第i個元素,以k/i的概率替換掉這個水庫中的某乙個元素。
證明概率相等:
首先要明白,如果最終k個元素確定,則這k個元素出現的概率都是k/n。
下面來證明當讀到第i個元素時,水庫中每個元素出現的概率是k/i。
1)初始情況:出現在水庫中的k個元素出現的概率都是1.
2)第一步:處理第k+1個元素的情況。分為兩種情況:水庫中元素都沒有被替換;水庫中某個元素被第k+1個元素替換掉。
對於情況2:第k+1個元素被選中的概率是k/(k+1),所以這個新元素在水庫中出現的概率就一定是k/(k+1)。下面看水庫中剩餘的元素出現的概率。水庫中人乙個元素被替換的概率是1/(k+1),那它出現在水庫中的概率就是k/(k+1)。可以看出新元素和舊元素出現的概率是相等的。
對於情況1:當元素全部都沒有替換掉的時候,每個元素的出現概率肯定是一樣的,這很顯然。但具體是多少呢?就是1-p(第k+1個元素被選中)=1-1/(k+1)=k/(k+1)。
即i=k+1的時候滿足
3)歸納法:重複上面的過程,只要證明第i步到第i+1步,所有元素出現的概率相等即可。
假設第i個元素也滿足水庫中每個元素出現的概率是k/i,則當第i+1個元素時:
第i+1個元素出現在水池中的概率為k/(i+1),很容易得到水庫中其他元素出現的概率也是k/(i+1)。
下面利用上面的方法從1-100之間選出3個數:
#include #include #include #include #include using namespace std;
const int n = 100;
const int pooln = 3;
int random(int min, int max)
void draw()
for (int i = 0; i < pooln; i++)
cout << re[i] << " ";
cout << endl;
}int main()
感覺有點問題,能夠保證random(min,max)產生的[min,max]中每個數的概率相等嗎? 海量資料面試題
海量資料面試題 1 給個超過100g的logfile,log中存著ip位址,設計演算法找到出現次數最多的ip位址?第一題 首先我們的思路就是利用雜湊進行檔案的切分,我們把100g大小的logfile分為1000份,那麼下來差不多沒乙個檔案就是100m左右,然後再利用雜湊函式除留餘數的方法分配到對應的...
海量資料面試題
給乙個超過100g大小的log le,log中存著ip位址,設計演算法找到出現次數最多的ip位址?思路 1 使用雜湊切割 將100g大小的檔案分成1000分小檔案 2 使用 hashstr ip 1000 將每個檔案上的ip位址對映到雜湊表中 然後將ip位址轉化成整數形式 3 使用key value...
海量資料面試題
方案1 可以估計每個檔案安的大小為50g 64 320g,遠遠大於記憶體限制的4g。所以不可能將其完全載入到記憶體中處理。考慮採取分而治之的方法。s 遍歷檔案a,對每個url求取clip image002,然後根據所取得的值將url分別儲存到1000個小檔案 記為clip image004 中。這樣...