正文
如何生成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 陣列訪問有較好的記憶體相聯性,而鍊錶則不能保...