生成k个小于n的互不相同的随机数

核心:让每个数被选中的概率都为k/n.
随机取出一个数,剩下的里面再取出一个数,重复k次。

方法一:利用洗牌的原理,将n个数(0至n-1)按次序排好,让最后一个数和一个随机(0~n-1)挑选出的位子进行互换,再让倒数第2个数和(0~n-2)位置中挑选出来的位置进行互换,依次执行k次,数组中的最后k个数就是得出的随机数。

方法二:来自Knuth的《The Art of Computer Programming, Volume2:Seminumerical Algorithms》的伪代码:
select = m
remaining = n
for i = [0,n)
	if (rand() % remaining) < select
		print  i
		select--
	remaining--
代码理解:针对第一个数使得它被选中的概率为k/n,第二个数使得它被选中的概率为k/n * (k-1)/(n-1) + (n-k)/n * k/(n-1),表示第一个数被选中后,第二个数被选中的概率+第一个数没被选上后,第二个数被选上的概率,……

错误方法:
利用洗牌的原理,将n个数(0至n-1)按次序排好,依次让每个数和一个随机挑选出的位子进行互换,这样肯定不会重复,而且次序被打乱,具有随机性。 只用交换k次,就可以取出k个小于n的互不相同的随机数。
原因:假设k=2,n=5,针对数组中的第一个元素,分析它被选取的概率:第一次执行,被选取的概率为1/5;第二次执行,首先第一个第一次不能不选取的概率为4/5,被换到数组中的第二个位置的概率为1/5,换到其他位置的概率和为3/5,如果在第二个位置被选取的概率为2/5,其他位置被选取的概率为1/5,总和为1/5 + 1/5 * 2/5 + 3/5 * 1/5 = 2/5。
针对数组中的第二个元素,第一次被选取的概率为1/5,第二次被选取的概率为:第一次没选到4/5 * 第二次选到的概率2/5= 8/25,总和为1/5 + 8/25 = 13/25,被选中概率增大。  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值