470. 用 Rand7() 实现 Rand10() 数学
难度中等
给定方法 rand7
可生成 [1,7]
范围内的均匀随机整数,试写一个方法 rand10
生成 [1,10]
范围内的均匀随机整数。
你只能调用 rand7()
且不能调用其他方法。请不要使用系统的 Math.random()
方法。
每个测试用例将有一个内部参数 n
,即你实现的函数 rand10()
在测试时将被调用的次数。请注意,这不是传递给 rand10()
的参数。
示例 1:
输入: 1 输出: [2]
示例 2:
输入: 2 输出: [2,8]
示例 3:
输入: 3 输出: [3,8,10]
# 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 """ #(randX() - 1)* Y + randY() 可以等概率的生成[1, X * Y]范围的随机数 while True: a = (rand7()-1) * 7 + rand7() #[1,49] if a <= 40: return a%10 + 1 a-= 40 #[1,9] a = (a-1)*7 + rand7() #[1,63] if a <=60: return a %10 + 1 a -= 60 #[1,3] a = (a-1)*7 + rand7() #[1,21] if a <= 20: return a %10 + 1
概率生成问题是一种比较常见的面试题,常见题型举例:
有一枚不均匀的硬币,要求产生均匀的概率分布
有一枚均匀的硬币,要求产生不均匀的概率分布,如 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