等概率无重复的从n个数中选取m个数

博客探讨了如何从n个数中等概率无重复地选取m个数的问题,介绍了两种方法:一是根据概率s/r选择下一个数,保证每个数被选中的概率为m/n;二是利用集合思想,按等概率选择不在集合中的随机数,直至集合元素达到m个。此外,还讨论了在未知总数n的情况下,如何进行等概率选择的方法。
摘要由CSDN通过智能技术生成

问题描述:程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内的m个随机整数,要求:每个数选择出现的概率相等,且按序输出。

学习过概率统计的同学应该都知道每一个数字被抽取的概率都应该为m/n. 那么我们怎么构造出这样的概率呢?在《编程珠玑》上面是这样解析的:

  依次考虑整数0,1,2,.....,n-1,并通过一个适当的随机测试对每个整数进行选择。通过按序访问整数,我们可以保证输出结果是有序的。 假如我们考虑m = 2,n = 5的情况,那么选择的每一个数字的概率都应该是2/5,我们怎么样才能做到呢?不慌张,慢慢来。

  下面给出我的分析过程:在0,1,2,3,4这五个数字中,我们依次对每一个数进行分析,第一次遇到0时,它的选择概率应该是2/5,如果选中了,我们开始测试第二个数1,这个时候因为1选中了,所以1这个数字的选中概率就变小了,变成1/4了,有人说这似乎不对吧,因为题目说让每一个数字选中的概率是一样大的,而现在?一个2/5,一个1/4,这怎么行呢?其实不是这样的,认真思考一下就知道了,数字1选中的概率等于什么? 数字1选中的概率p(1) = 数字0选中的概率 * (1/4) + 数组0没选中的概率*(2/4)这样推算下 (2/5 * 1/4) + (3/5 * 2/4) = 8/20 = 2/5 。这不就一样了吗?呵呵!下面给出来自Knuth的《The Art of Computer Programming, Volume2:Seminumerical Algorithms》的伪代码:

 

select = m
remaining = n
for i = [0,n)
     if (rand() % remaining) < select
             print  i
             select --
 
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设有一个包含n个数字的数组,数字的范围为1到m,现在从这个数随机抽k个数字,求这k个数至少有一个数重复出现的概率。 这个问题可以使用概率的补集思想来解决。即先求出这k个数没有数字重复出现的概率,然后用1减去这个概率即可得到至少有一个数重复出现的概率。 假设我们选取的第一个数字为x1,则后面选取的k-1个数不能有x1,因此后面选取的数字的范围为1到m-1。如果我们选取的第二个数字为x2,则后面选取的k-2个数不能有x2,因此后面选取的数字的范围为1到m-2。以此类推,对于第i个数字,后面选取的数字的范围为1到m-i+1。 因此,选取k个数字且没有数字重复出现的概率为: P1 = m*(m-1)*(m-2)*...*(m-k+1)/(m^k) 那么至少有一个数重复出现的概率为: P2 = 1 - P1 Java代码实现如下: ```java public static double probability(int n, int m, int k) { double p = 1.0; for (int i = 1; i <= k; i++) { p *= (double)(m-i+1) / m; } return 1 - p; } ``` 其,n为数组长度,m为数字范围,k为选取的数字个数。 例如,如果我们有一个包含10个数字的数组,数字范围为1到100,现在从数组随机抽3个数字,那么至少有一个数重复出现的概率为: ```java double p = probability(10, 100, 3); System.out.println(p); //输出0.264 ``` 因此,这个问题的答案是0.264。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值