您的位置:首页 > 其它

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

2014-03-06 09:31 459 查看
核心:让每个数被选中的概率都为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,被选中概率增大。  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: