从 n 个数字中选出 m 个不同的数字,保证这 m 个数字是等概率的

本文介绍了在面试中遇到的一道问题:如何从n个数字中选出m个不同的数字,保证这m个数字是等概率的。文章探讨了多种解法,包括使用线程标记序号、模拟过程、洗牌算法和动态概率选择,并对每种方法进行了详细解释,证明了这些方法能实现等概率选取。

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

问题如上。

这是我被面试的一个题目。我的第一反应给出的解决办法是,开启  n 个线程并标记序号,各个线程打印出它的序号。直到有 m 个线程被调度时,停止所有线程。 

打印出的序号即是 m 个等概率出现的数字。

面试官听到这个解决办法,吸了一口凉气,估计心里在想,这小伙疯了!我当时自知这个解决方案不是面试官想要的,于是说了,如果这个 n 很大,那么就要另

想办法了,因为不可能在一个进程里产生任意多个线程。

想啊想,过了两分钟,还是没有找到解决办法。面试官很 nice 让我回去后再想一想。

其实这个题细想,有些难度。你可能有一种思路:如果能一次性取出 m 个数字,再保证各数字是随机的,则可以满足等概率。但。。。如何一次性取出 m 个数字呢?

一次性生成多个随机数?如果生成的数字有相同则不是等概率的,因为这个数字比其它的数字出现的次数多,则概率大些(尽管你忽略了它出现多次)。或者还有思路:

每次出一个,保证取 m 次得到的各数字概率相等。听起来,似乎这种思路要难些。


[解法一]

我们来模拟这个过程,设有一个长度为 m 的辅助数组 B,用来装选中的数字。数组末满时,依次从长度为 n 的数组 A 中每次取一个数字顺序放入 B 中。直到 B 满了。

设对于后续的每一个元素,其装入 B 中的概率为 x。此元素装入 B 中的操作是将它与 B 中的某个元素置换。

则 B 中已经存在的某个元素,继续在 B 中存在的概率为:(1-x) + x*(m-1)/m,即当前取出的元素不进入 B,被直接舍弃࿰

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值