其他题目---蓄水池算法

【题目】

  有一个机器按自然数顺序的方式吐出球(1号球、2号、3号…),你有一个袋子,袋子最多只能装下K个球,并且除此之外你没有更多的空间。设计一种选择方式,使得当机器吐出第N号球的时候(N > K),你袋子中球的个数是K个,同时保证从1号球到N号球中的每一个,被选进袋子的概率是K/N。

【基本思路】

  这道题的核心解法就是蓄水池算法。过程如下:
  1、将第1~k个球直接放入袋子
  2、处理第i号球时(i > k),以k/i的概率决定是否将第i号球放入袋子中。如果不决定放入袋子,直接扔掉第i号球;否则,在袋子中随机选择一个扔掉,然后放入第i号球
  3、重复步骤2直到 i == N

  证明:

  对于第i号球进袋子的分析分两部分:

  1、当 1ik 时,那么在选第k+1号球时,第i号球留在袋子中的概率是1。

  在选第k+1号球的时候,只有决定第k+1号球入袋,并且第i号球正好被随机选中的时候,第i号球才会被淘汰。所以第i号球被淘汰的概率是 p=kk+11k ,所以第i号球留下来的概率就是 1p=kk+1 。那么从第1号球到第K+1号球的过程中,第i号球最终留下来的概率是 kk+1

  同理,在选第k+2号球的时候,第i号球被淘汰的概率是 p=kk+21k ,所以第i号球留下来的概率就是 1p=k+1k+2 。那么从第1号球到第K+2号球的过程中,第i号球最终留下来的概率是 kk+1k+1k+2

  依次类推,在选第N号球的时候,从第1号球到第N号球的过程中,第i号球最终留下来的概率是 kk+1k+1k+2...N1N=kN

  2、当 k<i 时,那么在选第i号球时,第i号球留在袋子中的概率是k/i。

  在选第i+1号球的时候,只有决定第i+1号球入袋,并且第i号球正好被随机选中的时候,第i号球才会被淘汰。所以第i号球被淘汰的概率是 p=ki+11k=1i+1 ,所以第i号球留下来的概率就是 1p=ii+1 。那么从第i号球被选中到第i+1号球的过程中,第i号球最终留下来的概率是 kiii+1

  同理,在选第i+2号球的时候,第i号球被淘汰的概率是 p=ki+21k ,所以第i号球留下来的概率就是 1p=i+1i+2 。那么从第i号球到第i+2号球的过程中,第i号球最终留下来的概率是 kiii+1i+1i+2

  依次类推,在选第N号球的时候,从第i号球到第N号球的过程中,第i号球最终留下来的概率是 kiii+1...N1N=kN

  所以,按照该方法,当吐出球数为N时,每一个球被选进袋子的概率都是K/N。

【代码实现】

#python3.5
def getKNumRand(k, max):
    def rand(max):
        return int(random.random() * max) + 1

    if k < 1 or max < 1:
        return None
    res = []
    for i in range(k):
        res.append(i+1)
    for i in range(k+1, max+1):
        if rand(i) <= k:
            res[rand(k)-1] = i
    return res
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值