如何构造另一个随机生成函数?

昨天下午面搜狐的时候被问到了构造随机数生成函数的问题,事后觉得有必要归纳一下相关题型。

1.已知随机数生成函数randA能等概率生成0~n的整数,设计一个等概率生成0~m的randB

算法:
若n大于m,则直接利用randA随机产生的数作为randB,如果randA产生的数大于m则丢弃这个数,重新产生,直至成功。若n远大于m,则只需构造最大值为m*(n/m)的随机函数randC,然后丢弃randA产生的数大于m*(n/m)的那部分即可得到randC。而randB=randC/(n/m)。执行k次仍然没能产生m以内的随机数的概率为((n-m*(n/m))/n)^k。
若n小于m,则利用n进制思路,实现一个随机生成函数randC=randA+randA*(n+1)+randA*(n+1)^2+..etc(一直这样构造,直到使得randC的最大值和randB或randB的倍数接近),randC生成各个数都是等概率的。此时randC>=randB*x (x是任意的倍数),然后丢弃大于的部分即可。若存在a使得((n+1)^a-1)/m可以整除,则存在无需丢弃的可能,否则不可能。

2.给定一个能以60%、40%概率生成0、1的随机函数randA,设计能各以50%概率生成0和1的随机函数

算法:
调用两次randA,有(0,0)、(0,1)…等总共四种情况,其中(0,1),和(1,0)发生的概率相等,那么可以丢弃(0,0),(1,1)这两种情况,则剩下的(1,0),(0,1)两种情况发生的概率都是50%。

3.给定random()函数,设计一个能以60%、40%概率生成0、1的随机函数

算法:
用random生成1~10之间的随机数,若产生的数在0~6范围则返回1,否则返回0。
如果要设计能以概率p1、p2、p3..pm概率生成0、1、2、…m的随机函数,则只需要将random函数
随机范围设置为(p1+p2+..pm)*100,例如若随机产生的数在取值范围p1*100~(p1+p2)*100时,则输出 2,以此类推进行处理。这种做法可以实现任意整数随机数的任意概率分布。如果要用一个连续分布实现另一个连续分布的随机函数,可以参考https://www.zhihu.com/question/20086207?sort=created

4.给定一个能以60%、40%概率生成0、1的随机函数,设计能以等概率生成1~n的新随机函数

算法:
先用问题2算法的思路,用题目给定的随机函数设计出等概率生成0,1的随机函数randA,再根据问题1算法的二进制的思路,用randA按位随机k=1+logn(以2为底)次,生成一个可能大于n的随机数,若大于n则抛弃,重新生成即可。

5.给定random,设计一个随机函数,使得0出现1次,1出现2次….n-1出现n次

算法:
把随机数看成是由两个能生成0~n-1之间数的随机函数之和 rand()+rand(),则:
n-1=(n-1)+0=(n-2)+1=(n-3)+2…=1+(n-2)=0+(n-1) 共有n种搭配
n-2=(n-2)+0=(n-3)+1=(n-4)+2…=1+(n-3)=0+(n-2) 共有n-1种搭配
…….
1=0+1=1+0 共有2种搭配

n-i 共有n-i+1种搭配,即满足题意,若随机函数之和大于n-1则丢弃即可。

6.给定random,设计一个随机函数,使得1出现1次,1出现1次….n出现n次

算法:
跟问题5算法思路相似, 新随机函数大概的形式为randC=randA()+randB()+a ,就是配置randA、randB、和a的参数使得满足题意:这里randA为能生成1~n的函数,randB为能生成0~n的函数,a为0:
n = n+0=(n-1)+1=…=1+(n-1) 共有n 种搭配
n-1=(n-1)+0=(n-2)+1=…=1+(n-2) 共有n-1种搭配
n-2=(n-2)+1=(n-3)+2=…=1+(n-3) 共有n-2种搭配
…….
1=1+0 共有1种搭配
n 共有n种搭配,即满足题意,若随机函数之和大于n则丢弃即可。

参考链接:
http://sumnous.github.io/blog/2014/05/13/random-pick-function/
http://blog.csdn.net/majianfei1023/article/details/7249918

你可能感兴趣的:(算法)