第七节 随机区间函数练习题
题目:假设函数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;
}
};