2018-12-09 16:40:30
问题描述:
问题求解:
这个问题字节跳动算法岗面试有问到类似的,有rand6,求rand8,我想了好久,最后给了一个特殊解法,就进行三次,每次取前三个数和后三个数的概率相等为1 / 2,那么最后需要得到的概率是1 / 8,就可以通过取三次得到。问题就转变成了映射的问题,当然映射的方式是很简单的,类似二进制的方法,很容易就可以进行映射。
但是,上述的解法在本题中是没有办法使用的,就需要更通用的解法,说实话,之前也没有做过Rejection Sampling标签下的题目,这个问题的通用解法就是使用拒绝采样的算法来进行解决。
首先我们肯定是需要对原空间进行扩充的,因为原空间的大小比生成空间的大小要小。
我其实最初想到的也是两次求rand7(),然后直接求和,但是很显然的这样得到的解空间中的1 - 10是不平均分配的,即使通过对10取余 + 1也不能得到等概率的解。
当然还有人可能会想通过求乘积的方式来扩充空间,可惜的是这样也是非等概率的,具体可以见下图:
扫描二维码关注公众号,回复:
4437365 查看本文章
那么怎么样才能得到等概率的呢?其实,我们只需要对两次取得的各个可能的数进行编号,每个编号不就是等可能的么?
由于编号的总长度大于10的倍数,后面的49 - 40 = 9个数字就需要抛弃掉。通过这种方式,我们就可以等概率的生成1 - 10这10个整数。
/** * The rand7() API is already defined in the parent class SolBase. * public int rand7(); * @return a random integer in the range 1 to 7 */ class Solution extends SolBase { public int rand10() { int res = Integer.MAX_VALUE; while (res >= 40) { res = 7 * (rand7() - 1) + rand7() - 1; } return res % 10 + 1; } }