蓄水池抽樣演算法:
當記憶體無法載入全部資料時,如何從包含未知大小的資料流中隨機選取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個數就是隨機選擇的。證明 這裡即需要證明每個數出現...