力扣470均匀随机数生成

        已知rand_N()可以均匀生成[1,N]间的随机数,则(rand_X() - 1) * Y + rand_Y()可以均匀生成[1,X * Y ]间的随机数,即实现了rand_XY()。

        如下所示,用如下代码可生成[1,63]间所有整数数据:

for i in range(0,7):
        for j in range(1,10):
            print(i * 9 + j, end=' ')
        print()

所得数据如下:

1 2 3 4 5 6 7 8 9 
10 11 12 13 14 15 16 17 18 
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63

        即可用(rand_7() - 1) * 9 + rand_9()表示rand_63()。

        则从rand_XY()取得rand_X()即可通过以下方法:rand_X() = rand_XY() % X + 1来实现。

        以上均为原理部分,接下来为实际操作部分,原题如下:

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

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

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

        首先将rand7 范围扩展到>=10,利用(rand_7() - 1) * 7 + rand_7()拓展到rand_49()。这时发现该数不是10的倍数,此时利用"拒绝采样"的知识,将大于40的数据全部拒绝,仅保留小于等于40的数据,得到rand_10() = rand_40() % 10 + 1。1-10间所有数据取到的可能均为4/49。

代码如下:

def rand_10():
    while(True):
        res = (rand7() - 1) * 7 + rand7()
        if res <= 40:
            return res % 10 + 1

         可以对该代码进行优化,即将拒绝的数据重复使用上面的方法,减少拒绝的数据,下面是改进代码:

def rand_10():
    while(True):
        res = (rand7() - 1) * 7 + rand7()
        if res <= 40:
            return res % 10 + 1
        res = (res - 40 - 1) * 7 + rand7()
        if res <= 60:
            return res % 10 + 1
        res = (res - 60 - 1) * 7 + rand7()
        if res <= 20:
            return res % 10 + 1

        

        下面是另一种方法:即利用两次rand_7()取得1/2和1/5的概率,将两者作乘法即可得到1/10的概率:

def rand_10():
    first, second = 0, 0
    while (first := rand7()) > 6:
        pass
    while (second := rand7()) >5:
        pass
    return second if first & 1 == 1 else 5 + second

        当然,若要取得类似rand_11()则可取得1/2和1/6的概率,并将数据12拒绝即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值