程式設計珠璣 Floyd隨機抽樣

2021-06-27 07:36:18 字數 966 閱讀 8512

對於n個樣本,如何均勻隨機的取出m個樣本?即n個樣本中每個樣本都能有m/n的概率被取中。

1.簡單插入取樣

這是最基本,最直觀的方法。在乙個初始為空的集合中插入1~n的隨機整數,知道個數為m個為止。但這個方法有個弱點,就是要插入乙個數時,判斷集合中是否存在該數,如果其存在,則要繼續取樣直到取到乙個不在原集合中的數,重複取樣需要很大的開銷,而且越到後來開銷越大。

2.floyd取樣(將第n個數插入與前n-1個數的樣本的選取關聯起來)

floyd取樣是大名鼎鼎的robert w. floyd提出來的。其基本思想:當已經在[1,n-1]個區間中已隨機取出m-1個樣本時,這時,生成乙個1~n的隨機數,如果該數落在原來的m-1個樣本中,則樣本集合加入n;如果不落在原來的m-1個樣本中,那麼就將隨機數加入已取樣本集合。這樣的演算法複雜度為o(m)

證明:歸納法證明

假設floyd演算法在[m-1,n-1]時任意乙個數被選中的概率是m-1/n-1. 則當[m,n]時

1. 對於第n個數,其被選中的概率為1/n+(m-1)/n=m/n; n被選中有兩個可能,乙個是隨機數在m-1個樣本裡,則概率為

m-1/n。另一種是不在,則將隨機數加入,隨機數為n的概率為1/n。所以總的概率為1/n+(m-1)/n=m/n;

2. 對於前面 n-1個數中的任意乙個數,總被選中的概率p=上一輪被選中的概率+上一輪未被選中的概率*本輪被選中的總概率

易得p=(m-1)/(n-1)*1+(n-m)/(n-1)*1/n=m/n.

本輪被選中的概率: 1/n

p=(m-1)/n-1+(n-m)/(n-1)*1/n=m/n;

遞迴實現:

void floyd(int m,int n,set&s)else

}

迭代實現

void floyd2(int m,int n,set&s)else

}}

mR 隨機抽樣

1.問題由來 google曾經有一道非常經典的面試題 給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 這道題的解法非常多,網上討論也非常熱烈。本文要討論的是...

MySQL隨機抽樣

最近由於需要大概研究了一下mysql的隨機抽取實現方法。舉個例子,要從tablename表中隨機提取一條記錄,大家一般的寫法就是 select from tablename order by rand limit 1。但是,後來我查了一下mysql的官方手冊,裡面針對rand 的提示大概意思就是,在...

R隨機抽樣

x為總體向量 n為樣本容量 replace f表示無放回抽樣 replace t表示放回抽樣 prob可以設定不等概率抽樣 sample x,n,replace f,prob null 用r模擬擲硬幣 h表示正面 t表示反面 有放回抽樣 sample c h t 10,replace t 1 h t...