Python实现:现在有一个随机数生成器, 1/3概率生成1, 2/3生成0, 如何基于这个生成器, 得出一个1/2概率是0, 1/2概率是1的生成器?

今天看到一道字节跳动后台开发岗的面试题,题目如下:

现在有一个随机数生成器, 1/3概率生成1, 2/3生成0, 如何基于这个生成器, 得出一个1/2概率是0, 1/2概率是1的生成器?

 

思路:

可以将结果看过一个二元组,那么有4种情况分别是(0,0),(0,1), (1,0),(1,1)

其中 p((0,0)) = 4/9

        p((1,1)) = 1/9

        p((0,1)) = 2/9

        p((1,0)) = 2/9

那么,我们只需按  1/3概率生成1, 2/3生成0  这个规则,生成二元组,将结果中的(0,0)和(1,1)抛弃,剩下的(0,1)即为1,(1,0)即为0,

 

代码:

import random
from fractions import Fraction


# 返回类型是tuple,因为list不可哈希
def random_pick(some_list, probabilities):  # 按照规则生成二元组
    result = ()  # 二元组结果
    for i in range(0, 2):  # 构造二元组
        cumulative_probability = 0.0  # 初始化概率值
        x = random.uniform(0, 1)  # 随机生成一个0到1之间的值
        for item, item_probability in zip(some_list, probabilities):  
            cumulative_probability += item_probability  # 累加规则中的概率值
            if x < cumulative_probability:  # 如果x在0到1/3内,添加1;如果在1/3到1,添加0
                result += (item,)
                break
    return result


def random_filter(num):
    a = [1, 0]
    b = [Fraction(1, 3), Fraction(2, 3)]  # 概率分布
    all_collection = [(0, 1), (1, 0), (0, 0), (1, 1)]  # 所有结果
    result_collection = [(0, 1), (1, 0)]  # 我们需要的结果
    all, re, count = dict(zip(all_collection, [0] * 4)), dict(zip(result_collection, [0] * 2)), 0  # 前两个变量为所有结果和需要结果的dict,最后一个count变量为需要结果的计数
    for x in range(num):
        result = random_pick(a, b)
        all[result] += 1
        if result in result_collection:
            count += 1
            re[result] += 1
    for v, value in re.items():
        re[v] = float(value)/count
    for v, value in all.items():
        all[v] = float(value)/num
    return all, re  # 返回所有结果和需要结果,所有结果all 用来验证四种情况是不是2/9 2/9 4/9 1/9分布,需要结果re 用来验证是不是得到了最后的1/2的0和1/2的1的生成器


for item in random_filter(100000):  # 做10万次生成试验
    print(item)





 

输出:

我们可以看到,(0,1) 和 (1,0)皆约等于2/9,(0,0)约等于4/9,(1,1)约等于1/9,表明我们得到的所有结果是没啥大问题的,然后再看 (0,1) 和 (1,0) 的结果,可以发现是非常接近的(其实只要用第一行的值相除一下就行),因此符合题目要求。

{(0, 1): 0.22255, (1, 0): 0.22182, (0, 0): 0.44584, (1, 1): 0.10979}
{(0, 1): 0.50082138758242, (1, 0): 0.49917861241757994}

 以上是我的解法,如果有更的解法请在下方评论,大家一起学习学习。

 

你可能感兴趣的:(算法与数据结构)