【阿里面试题】已知foo()方法能以各50%概率返回0或1,基于foo()方法实现boo()方法,能以各10%的概率返回[0-9]中的一个数字(Python解法)
程序员文章站
2022-05-28 11:52:59
...
前几天在网上看到这样一道面试题,据说是阿里的题目
自己想到了一个方法,希望大家指正。代码如下:
import random
# 题中foo()为已知方法,所以这里我们用内置random模块实现
def foo():
return random.randint(0,1)
# 这里开始实现boo()方法
def boo():
# 初始化空字符串,用来存储二进制数
s = ''
for _ in range(4):
# 拼接foo()方法生成的数字
s += str(foo())
# 二进制转十进制
i = int(s,2)
# 如果数字不大于9,则直接返回结果。否则重新运行,即一次递归
if i <= 9:
return i
else:
return boo()
接着运行我们的方法10万次,看看概率是不是约为10%
n_loop = 100000
tmp_dict = {}
for _ in range(n_loop):
i = boo()
tmp_dict[i] = tmp_dict.get(i,0) + 1
print('在{}次测试中:'.format(n_loop))
for i in range(10):
count_i = tmp_dict[i]
prob_i = count_i / n_loop * 100
count_i_txt = str(count_i).rjust(5)
prob_i_text = '{:.2f}'.format(prob_i).rjust(5)
print('数字{}出现了{}次,概率约为{}%'.format(i,count_i_txt,prob_i_text))
输出为:
下面开始解析:
方法的核心思想为,利用每次生成的0或1,拼接为一个二进制数字,并且将其转换为10进制。由于要求[0-9]的数字,所以我们选择4位的二进制。即运行foo()方法4次,生成一个4位的二进制数,其取值范围为[0-15] (即二进制范围[0000 - 1111])。假如我们不做任何处理,那么这个方法会以各1/16的概率输出[0-15]中任意一数。接着我们做一个限制,当数字大于9时,重新运行此方法,直到数字在[0-9]之间。由于每个数字是等概率出现的,所以该方法的实际输出概率为10%。
更直观的来说,本题实际要求是构造一个数字[0-9]的10面骰子,然而我们不知道如何直接构造10面骰子,所以我们构造了一个数字[0-15]的16面骰子,并制定了如下规则:“如果摇到大于9的数字则重新摇,直到结果在[0-9]之间”。
有的人可能会感到疑惑:这样概率难道不是1/16吗?事实上,如果我们不做任何限制,那么的确如此。但同时我们也应该知道一个事实:每个数字是等概率的。所以我们并不关心每个数字在方法内部生成时的概率,只要每个数字是等概率的,并且该方法只返回[0-9]的数字,那么该方法输出每个数字的实际概率就是1/10 = 10%
。
思考: 我暂时没想出来如何直接构造一个10面的骰子,如果有人能想到,请一定要告诉我。
上一篇: Qt5.8.0安装
下一篇: QSplitter 分割窗口