C實現蓄水池抽樣演算法

2021-10-20 20:55:46 字數 2250 閱讀 3720

蓄水池抽樣演算法:

當記憶體無法載入全部資料時,如何從包含未知大小的資料流中隨機選取k個資料(每一次讀都只是k個數),並且要保證每個資料被抽取到的概率相等。

*隱含條件:*只能順序讀取,然後保證每個數讀取的概率都相同,隨機讀取k個,也就是說記憶體內最多只能裝下k個資料

1.當 k = 1 時

即此題的情況也就是說,我們每次只能讀乙個資料。

假設資料流含有n個數,我們知道如果要保證所有的數被抽到的概率相等,那麼每個數抽到的概率應該為 1/n

那如何保證呢?

先說方案:

每次只保留乙個數,當遇到第 i 個數時,以 1/i的概率保留它,(i-1)/i的概率保留原來的數。

舉例說明: 1 - 10

遇到1,概率為1,保留第乙個數。

遇到2,概率為1/2,這個時候,1和2各1/2的概率被保留

遇到3,3被保留的概率為1/3,(之前剩下的數假設1被保留),2/3的概率 1 被保留,(此時1被保留的總概率為 2/3 * 1/2 = 1/3)

遇到4,4被保留的概率為1/4,(之前剩下的數假設1被保留),3/4的概率 1 被保留,(此時1被保留的總概率為 3/4 * 2/3 * 1/2 = 1/4

以此類推,每個數被保留的概率都是1/n。

2.當k=m (m>1)

對任意n個數,抽取k個數,每乙個數被抽到的概率都是k

n\frac

nk​假設記憶體最大為k,當前k 個資料時候,每乙個都會被保留,概率為1,當第k+1個到來時候,抽到這個數的概率是kk+

1\frac

k+1k

​*,那麼在前k個數中任意乙個數保留下來的概率是

p=(未抽到第k+1) * (前k個中選k個) +(抽到第k+1) * (前k個中選k-1個)

如下:

假設第 i 個資料到來,前 i-1個數抽k個每乙個抽中的概率是ki−

1\frac

i−1k​,

p=(未抽到第 i ) * (前 i-1個中選k個) +(抽到第 i ) * (前 i-1 個中選k-1個)

**實現:

高階:如果鍊錶十分大且長度未知,如何解決這個問題?你能否使用常數級空間複雜度實現?

示例:// 初始化乙個單鏈表 [1,2,3].

listnode head = new listnode(1);

head.next = new listnode(2);

head.next.next = new listnode(3);

solution solution = new solution(head);

// getrandom()方法應隨機返回1,2,3中的乙個,保證每個元素被返回的概率相等。

solution.getrandom();

//蓄水池抽樣法。使用rand函式來進行實現。

/*rand產生乙個0-0x7fff的隨機數,即最大是32767的乙個數

如果想要表示乙個數是從0開始到最大值的,比如說,想要產生乙個0-99之間的隨機數,那麼用法如下

int num = rand() % 100;

如果想要產生乙個數是從1開始到最大值的,比如說,想要產生乙個1-100之間的隨機數,那麼用法如下

int num = rand() % 100 + 1;

*/typedef

struct

solution;

/** @param head the linked list's head.

note that the head is guaranteed to be not null, so it contains at least one node. */

solution*

solutioncreate

(struct listnode* head)

/** returns a random node's value. */

intsolutiongetrandom

(solution* obj)

else

} temp = temp->next;

}return res;

}void

solutionfree

(solution* obj)

演算法 蓄水池抽樣

例題 有乙個機器按自然數序列的方式吐出球,1號球,2號球.現有乙個袋子,袋子裡最多只能裝下k個球,並且除袋子以外沒有更多的空間,球扔掉不能放回。設計一種選擇方式,使得當機器吐出第n號球時,袋子中的球數是k個,同時可以保證從1號球到n號球中的每乙個被選中進袋子的概率都是k n。具體例子 有乙個只能裝下...

蓄水池抽樣演算法

給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 蓄水池抽樣演算法 該演算法是針對從乙個序列中隨機抽取不重複的k個數,保證每個數被抽取到的概率為k n這個問題...

蓄水池抽樣演算法

題目 要求從n個元素中隨機的抽取k個元素,其中n無法確定 解法 首先選擇n中的前k個數加入 蓄水池 中,然後從第k 1個數開始,以k k i i 1,2,3.的概率選擇這個數,然後在蓄水池中隨機選擇乙個數,並將其替換,n個元素遍歷完畢後,蓄水池中的k個數就是隨機選擇的。證明 這裡即需要證明每個數出現...