字节跳动面试题.如何等概率地大小为n的数组中选取m个整数(python)

本文详细解析了两种从数组中随机选取元素的算法,一种适用于已知数组大小的情况,另一种适用于数据流不确定的情况,采用蓄水池抽样方法,确保每个元素被选中的概率相等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:随机的从大小为n的数组中选取m个整数,要求每个元素被选中的概率相等。

分析与解答:首先从有N个元素的数组中随机选出一个元素,然后把这个选中的数字与数组中第一个元素交换,接着从数组后面N-1个数字中选出1个元素与数组中第二个元素交换,以此类推,直到选出m个数字为止,数组前m个数字就是随机选出来的m个数字,且他们被选中的概率相同。


————————————————
版权声明:本文为优快云博主「蜡笔小新灬」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_42013574/article/details/89103823

import random
 
 
def getRandomM(a, n, m):
    if a == None or n <= 0 or n < m:
        print("参数不合理")
        return
 
    i = 0
    while i < m:
        j = random.randint(i, n - 1)  # 获取[i到n-1]间的随机数
        # 随机选出的元素放到数组的前面
        tmp = a[i]
        a[i] = a[j]
        a[j] = tmp
        i += 1
 
 
if __name__ == "__main__":
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    n = 10
    m = 6
    getRandomM(a, n, m)
    i = 0
    while i < m:
        print(a[i], end=" ")
        i += 1

上题中如果n的大小不确定(可以认为是⼀个数据流),如何做?

链接:https://www.nowcoder.com/questionTerminal/12796031452e4ced8a16255bb02c4168
来源:牛客网
 

蓄水池抽样

具体方法:我们先选取前m个数放入池中,然后我们每次以m/k的概率选择第k(k>m)个数a[k],然后再在蓄水池中随机选取一个元素a[j],交换a[k]和a[j];

代码:

 

[cpp] view plain copy

  1. Init : a reservoir with the size: m  
  2.         for    i= m+1 to N    
  3.             j=random(1, i);    
  4.             if( j < m)    
  5.                  SWAP the jth value and ith value    
  6.        end for   

 

接下来证明:

假设当前是i+1, 按照我们的规定,i+1这个元素被选中的概率是m/i+1,也即第 i+1 这个元素在蓄水池中出现的概率是m/i+1 
此时考虑前i个元素,如果前i个元素出现在蓄水池中的概率都是m/i+1的话,说明我们的算法是没有问题的。 

对这个问题可以用归纳法来证明:m < i <=N 
1.当i=m+1的时候,蓄水池的容量为m,第m+1个元素被选择的概率明显为m/(m+1), 此时前k个元素出现在蓄水池的概率为 m/(m+1), 

很明显结论成立。 

 

2.假设当 j=i 的时候结论成立,此时以 m/i 的概率来选择第i个元素,前i-1个元素出现在蓄水池的概率都为m/i。 
证明当j=i+1的情况: 
即需要证明当以 m/i+1 的概率来选择第i+1个元素的时候,此时任一前i个元素出现在蓄水池的概率都为m/(i+1). 
前i个元素出现在蓄水池的概率有2部分组成, ①在第i+1次选择前得出现在蓄水池中; ②得保证第i+1次选择的时候不被替换掉 
①.由2知道在第i+1次选择前,任一前i个元素出现在蓄水池的概率都为m/i 
②.考虑被替换的概率: 
首先要被替换得第 i+1 个元素被选中(不然不用替换了)概率为 m/(i+1),其次是因为随机替换的池子中m个元素中任意一个,所以不幸被替换的概率是 1/m,故 前i个元素(池中元素)中任一被替换的概率 = m/(i+1) * 1/m = 1/(i+1),则(池中元素中)没有被替换的概率为: 1 - 1/(i+1) = i/(i+1)
综合① ②,通过乘法规则 
得到前i个元素出现在蓄水池的概率为 m/i * i/(i+1) = m/(i+1) 
故证明成立

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值