程式設計珠璣 第十二章 取樣問題

2021-08-26 21:56:43 字數 2033 閱讀 8167

一,概述

問題描述:如何生成0~n-1內的m個隨機整數(

不重複)

需求:按序輸出,並且保證每個子集被選中的可能性相等。

1)給出下面**

#include "stdio.h"

#include "stdlib.h"

#include "time.h"

void getrandnumber(int m,int n)//在0 -- n-1 中挑選m個 隨機數

int main()

c++模板插入操作在o(logm)時間內完成,而遍歷集合需要o(m)時間。所以完整程式需要o(mlogm)時間

4)生成隨機數的另一種方式:把包含0 - n-1的陣列順序打亂,然後把前m個元素輸出。

更好的方式是,我們只需要打亂前m個元素,然後排序輸出。

或者生成大於n個1 - n範圍的隨機數,然後去掉重複的,輸出前面的m個元素

#include #include using namespace std;

void sort(int a,int m)

void getshuf(int m,int n)//在0 -- n-1 中挑選m個 隨機數

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

int main()

10)問題:如何隨機從n個物件中選擇乙個物件,這n個物件是按序排列的,但是在此之前你並不知道n的值?

具體些說,在事先並不知道行數的情況下,如何讀乙個文字檔案,隨機選擇並輸出一行?

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

i = 0 while more input lineswith probability 1.0/++ichoice = this input line //如果前面做了選擇,並不會break,而是直到最後乙個為止。print choice

這裡比較有些疑惑的是第一行:總是選第一行 為什麼概率還是1/n?

概率=1*(1/2)*(2/3)*(3/4)……(n-1/n) =1/n

證明:當做第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如何輸出即可。要想獲勝,只需要1,2先輸出,三個數的全排列中這種情況有2種。所以獲勝概率為2/6

=1/3

程式設計珠璣第十二章習題

1.rand 一般返回約15個隨機位。用該函式實現bigrand 和randint l,u 要求前者至少返回30個隨機位,後者返回 l,u 範圍內的乙個隨機整數。int bigrand int randint int l,int u 2.在0 n 1範圍內選擇m個整數,在該範圍內隨機選擇乙個數i,然...

Objective C 程式設計 第十二章

預處理程式語句使用 開頭,一行中的第乙個非空字元。大部分內容都與c語言類似,相當於複習啦。預定義不是變數。不能為它賦值。實際上是字元的簡單替換。define語句常放在 import或 include語句後邊。定義乙個名稱後,可以在任何地方使用。一般放在標頭檔案,方便在多個原始檔中使用。所有預定義的名...

第十二章 併發程式設計

1 併發 邏輯控制流在時間上重疊 2 併發程式 使用應用級併發的應用程式稱為併發程式。3 三種基本的構造併發程式的方法 1 需要乙個sigchld處理程式,來 僵死子程序的資源。2 父子程序必須關閉各自的connfd拷貝。對父程序尤為重要,以避免儲存器洩露。3 套接字的檔案表表項中的引用計數,直到父...