程式設計珠璣第12章

2021-05-28 14:41:09 字數 2454 閱讀 6114

正文

如何生成0~n-1內的m個隨機整數

1、方法一

比如要從5個數里選出2個數,第乙個數的概率是2/5,第二個數的概率是1/4,然後是0/3

那麼現在已經很清楚了。

可以寫**如下:

for (int i = 0; i < n; ++i)

if (rand() %(n-i) < m)

2、方法二

可以用乙個set,每生成乙個隨機,就去set裡面檢視一下有沒有在set裡面,如果沒有就插入進去,直到set大小為m.

其實用雜湊應該更快。

3、方法三

首先把生n個隨機數(注意範圍),用第一章裡面講到的隨機數唯一生成演算法生成之後,取前面m個就可以了。

4、方法四

for (int j = n - m; j < n; ++j)

習題

1、參***

int bigrand()

int region(int l, int u) //[l, u]

2、演算法導論中提到過這個問題,可以這樣設計一下,隨機選擇乙個數,隨其後的m個數就被選中(假設這些數排列成圓形)。

3、當m < n/2時,

總共試了k次,則前面k-1次找到的數都是在集合中,那麼只有第k次不在裡面,那麼概率

p = (m/n)^(k-1) * (n-m)/n

那麼期望是 連加 k = 1至無窮大,根據二項式分布可知,期望等於

n/(n-m) < 2

從而可知得證

4、這裡可以看一下演算法導論裡面的中文版64頁的題目,把n個球投到m個框中,每個框中至少有乙個球時,至少要投mlgm次。

如果是n則是nlogn.

5、6、

7、非遞迴的**在正文中,是按照公升序進行輸出。

第二個問題,生成n個元素的m元子集的所有情況,應該可以使用dfs來進行處理。

8、先生成這些數,然後再按第一章的處理,生成亂序的情況。

呼叫m次隨機數函式生成器。輸出即可。

9、使用floyd的生成演算法。

10、答案可能比較難想到。

問題:如何隨機從n個物件中選擇乙個物件,這n個物件是按序排列的,但是在此之前你並不知道n的值?具體些說,在事先並不知道行數的情況下,如何讀乙個文字檔案,隨機選擇並輸出一行?

證明:解答:我們總是選擇第一行,並使用二分之一的概率選擇第二行,使用三分之一的概率選擇第三行,以此類推。在該過程結束的時候,每一行具有相同的選中概率(1/n,其中n是檔案的總行數):

i = 0

while more input lines

with probability 1.0/++i

choice = this input line  //如果前面做了選擇,並不會break,而是直到最後乙個為止。

print choice

證明:當做第i步選擇(選擇第i行)時,選擇該行的概率為1/i,則不選擇的概率為(i-1)/i

對於一篇有n行的文件,現需證明最終選定第i行的概率為1/n。

當最終選擇第i行,前(i-1)步的選擇對最終結果不會產生影響,第i步選擇的概率為1/i,即選擇第i行,第(i+1~n)步中均採取不選擇的動作,即對於任意j(i+1<=j<=n),當前步的概率為(j-1)/j,那麼最終的概率為:

(1/i)*((i)/(i+1))*...*((n-1)/n) = 1/n

以一篇只有6行的文件為例,最終選擇第2行的概率為:

1/2*(2/3)*(3/4)*(4/5)*(5/6) = 1/6

擴充套件:原問題可簡化為:

如何從n個有序物件中等概率地任意抽取1個,簡記為sample(n,1),其中n未知;

若將該問題改為:

如何從n個有序物件中等概率地任意抽取m個,簡記為sample(n,m),其中n未知;

分析:若n已知,sample(n,m)是普通的抽樣問題;當n未知時,可否根據上述演算法進行相應的轉化求解?

解決方案:

將sample(n,m)問題轉化為m個sample(n*,1)問題,更具體一點是,轉化為

sample(n,1);sample(n-1,1);sample(n-2,1)....;sample(n-m+1,1)問題。

仍然以一篇6行文件為例,任取其中2行,做法如下:

第一遍,以如下概率選中一行:

1(1)   2(1/2)  3(1/3)  4(1/4)  5(1/5)  6(1/6)

假設選中第2行,接著概率修改如下:

3(1)  4(1/2)  5(1/3)  6(1/4)  1(1/5)

[說明]:當選中第2行,從第3行開始修改概率,並將第2行排除在外,繼續掃瞄,這樣能保證在剩下的5個數中仍然以等概率抽取其中的乙個。

11、實際上如查刮到1,2,3以外的數,就繼續,所以看遇到這三個數中的哪乙個,所以勝的概率是2/3,輸的概率是1/3

程式設計珠璣筆記 第12章 取樣問題

整理了這一章提到的幾個演算法,其中蓄水池演算法書中沒有寫,這裡放在一起比較一下,出了方法2是c 的 其它都是python的實現。問題 程式的輸入包括兩個整數m和n,其中m 1 以特定概率順序選擇每乙個數 如果要從r個剩餘的整數中選出s個,則以s r的概率選擇剩餘整數中的第乙個整數,然後遞迴處理剩下的...

程式設計珠璣第14章

這裡把所有關於堆的操作寫出來。當做標程吧。include include define ms 1025 typedef struct heap heap heap h static void shift heap h,int i else break a i t static void increa...

程式設計珠璣第13章

正文 為了解決在12章中的隨機數問題,本章中的目的是對檢視是否在陣列中的情況進行處理。那麼這裡採用了以下幾種方法 1 採用c 的set 2 採用陣列 3 採用鍊錶,順序搜尋,插入時不用移動。結果是陣列的比鍊錶的要快 1 鍊錶需要讀入的記憶體數比陣列大 2 陣列訪問有較好的記憶體相聯性,而鍊錶則不能保...