题意:已知一个函数可以uniformly randomly产生1-7,由此构造一个函数可以uniformly randomly产生1-10。
首先rand7()+rand7()%4无法保证uniform,因为rand7()%4产生的0-3的概率就不是uniform的。这可以把rand7()和rand7()%4产生的所有组合列出来看一下,看看每个sample出现次数是否相等。
用两个rand7()进行加减操作,将1-10 map到一个Discrete space中且sample出现的次数相等。可以构造x(rand7()-1)+rand7(),因为还需要保证1,2,...,7出现,所以前面一项需要有一定的概率出现0,前面一项=1时,总和不能和1,...,7重合,所以x*1+1=8,then x=7.所以构造7*(rand7()-1)+rand7()即可。
另外,7*(rand7()-1)+rand7()产生的序列是1,2,...,49,mod 10的话,41-49是只能包括1-9,无法保证1-10每个都出现一次,是多余的,所以如果产生了41-49的数就要skip,重新random。这就相当于re-scale了probability,mask了invalid sppearance (41-49),所以仍然是uniform的。这种方法也叫rejection sampling。
// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7
class Solution {
public:
int rand10() {
while(true)
{
int tmp=7*(rand7()-1)+rand7();
if(tmp<=40)
{
return tmp%10+1;
}
}
}
};