470. 用 Rand7() 实现 Rand10()

发布时间 2023-07-01 17:18:10作者: 乐乐章

 

难度中等

给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。

你只能调用 rand7() 且不能调用其他方法。请不要使用系统的 Math.random() 方法。

每个测试用例将有一个内部参数 n,即你实现的函数 rand10() 在测试时将被调用的次数。请注意,这不是传递给 rand10() 的参数。

 

示例 1:

输入: 1
输出: [2]

示例 2:

输入: 2
输出: [2,8]

示例 3:

输入: 3
输出: [3,8,10]

 

 

 

概率生成问题是一种比较常见的面试题,常见题型举例:

有一枚不均匀的硬币,要求产生均匀的概率分布
有一枚均匀的硬币,要求产生不均匀的概率分布,如 0.25 和 0.75
利用 Rand7() 实现 Rand10()

不均匀硬币,产生等概率
现有一枚不均匀的硬币 coin(),能够返回 0、1 两个值,其概率分别为 0.6、0.4。要求使用这枚硬币,产生均匀的概率分布。即编写一个函数 coin_new() 使得它返回 0、1 的概率均为 0.5。


// 不均匀硬币,返回 0、1 的概率分别为 0.6、0.4
int coin() {
return (rand() % 10) > 5;
}
统计抛两次硬币的结果的概率分布:

结果 0 1
0 0.6*0.6=0.36 0.6*0.4=0.24
1 0.4*0.6=0.24 0.4*0.4=0.16
不难发现,连续抛两枚硬币得到 0 1 和 1 0 的概率分布是相同的。因此这道题的解法就是连续抛两次硬币,如果得到 0 1,返回 0;如果得到 1 0,返回 1;如果两次结果相同,则重新抛。

以此类推,无论这枚不均匀硬币的概率是多少,都可以用这种方法得到等概率的结果。

代码如下:


int coin_new() {
while (true) {
int a = coin();
if (coin() != a) return a;
}
}

 

 

 

 

一、大随机数生成小随机数 : rand7()实现rand5()

如果X大于Y,例如通过rand7()实现rand5(),rand7可以等概率的生成1-7,这里面包含了1到5。我们可以直接舍弃6和7来实现随机生成1至5(如下代码),那么有一个问题,这样的rand5生成的每个数是等概率的吗?

int rand5() {
    while (true) {
        int a=rand7();
        if (a<=5) return a;
    }
}



 

(randX() - 1)* Y + randY() 可以等概率的生成[1, X * Y]范围的随机数
 
# The rand7() API is already defined for you.
# def rand7():
# @return a random integer in the range 1 to 7

class Solution:
    def rand10(self):
        """
        :rtype: int
        """
        while 1:
            a = (rand7() -1 )*7  + rand7()  #[0,6] * 7 + [1,7] = [1,49]
            if a<=40:
                return a%10+1    
            a = a - 40 # [1,9]
            a = (a -1 )*7 + rand7() #[0,8]*7 + [1,7] = [1,63]
            if a <= 60:
                return a%10+1
            a = a - 61 #[1,3]
            a = (a -1)*7 + rand7() #[0,2]*7 + [1,7] = [1,21]
            if a<=20:
               return a%10+1