第七節 隨機區間函數練習題
題目:假設函數f()等機率隨機返回一個在[0,1)範圍上的浮點數,那麼我們知道,在[0,x)區間上的數出現的機率為x(0<x≤1)。給定一個大於0的整數k,並且可以使用f()函數,請實現一個函數依然返回在[0,1)範圍上的數,但是在[0,x)區間上的數出現的機率為x的k次方。
思路:調用k次,返回較大的數即可。相當於伯努利實驗,在[0,x)區間上的數出現的機率為x,因為機率的獨立的,所以重複k次,最終的機率就是x的k次方。
class RandomSeg {
public:
// 等機率返回[0,1)
double f() {
return rand() * 1.0 / RAND_MAX;
}
// 通過調用f()來實現
double random(int k, double x) {
double res=-1;
for(int i=0;i<k;i++){
res=max(res,f());
}
return res;
}
};
第八節 隨機數組列印練習題
題目:給定一個長度為N且沒有重複元素的數組arr和一個整數M,實現函數等機率隨機列印arr中的M個數。
思路:產生0-N-1之間的隨機數,作為索引index,列印arr[index]即可。
class RandomPrint {
public:
vector<int> print(vector<int> arr, int N, int M) {
vector<int> res(M);
int index;
for(int i=0;i<M;i++){
index=rand()%N;
res[i]=arr[index];
}
return res;
}
};
第9節 機器吐球練習題
題目:有一個機器按自然數序列的方式吐出球,1號球,2號球,3號球等等。你有一個袋子,袋子裡最多隻能裝下K個球,並且除袋子以外,你沒有更多的空間,一個球一旦扔掉,就再也不可拿回。設計一種選擇方式,使得當機器吐出第N號球的時候,你袋子中的球數是K個,同時可以保證從1號球到N號球中的每一個,被選進袋子的機率都是K/N。舉一個更具體的例子,有一個只能裝下10個球的袋子,當吐出100個球時,袋子裡有10 球,並且1~100號中的每一個球被選中的機率都是10/100。然後繼續吐球,當吐出1000個球時,袋子裡有 10 個球,並且1~1000號中的每一個球被選中的機率都是10/1000。繼續吐球,當吐出i個球時,袋子裡有10個球,並且1~i號中的每一個球被選中的機率都是10/i。也就是隨著N的變化,1~N號球被選中的機率動態變化成k/N。請將吐出第N個球時袋子中的球的編號返回。
思路:當N小於k時,N必定選進袋子,否則以k/N的機率選進袋子。
class Bag {
public:
vector<int> ret;
// 每次拿一個球都會調用這個函數,N表示第i次調用
vector<int> carryBalls(int N, int k) {
if(N<=k)
ret.push_back(N);
else{
int index=rand()%N;
if(index<k)
ret[index]=N;
}
return ret;
}
};