欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【阿里面试题】已知foo()方法能以各50%概率返回0或1,基于foo()方法实现boo()方法,能以各10%的概率返回[0-9]中的一个数字(Python解法)

程序员文章站 2022-05-28 11:52:59
...

前几天在网上看到这样一道面试题,据说是阿里的题目
【阿里面试题】已知foo()方法能以各50%概率返回0或1,基于foo()方法实现boo()方法,能以各10%的概率返回[0-9]中的一个数字(Python解法)

自己想到了一个方法,希望大家指正。代码如下:

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))

输出为:
【阿里面试题】已知foo()方法能以各50%概率返回0或1,基于foo()方法实现boo()方法,能以各10%的概率返回[0-9]中的一个数字(Python解法)


下面开始解析:

方法的核心思想为,利用每次生成的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面的骰子,如果有人能想到,请一定要告诉我。

相关标签: python python3