随机取样和洗牌算法

有一个长度为n的数组,想对其中的元素进行洗牌,使他们能够随机的分布,随机的意思是使每个元素在每个位置上出现的概率都是1/n。

 

如何去做呢,有一个方法如下:

  依次遍历所有的元素,在遍历到第i个元素的时候,有1/i 的概率和前i个元素(包括第i个)其中之一进行交换,则遍历完所有的元素之后,

得到的新的数组就满足上面提到的随机分布的条件。

 

写成代码如下:

 

 

证明如下:

 

1、当只有1个元素的时候,他的概率是1/1

2、当有2个元素的时候,遍历到第2个元素的时候,有1/2的概率与前2个元素交换,则第1个和第2个元素出现在第1个位置和第2个位置的概率都是1/2

3、k+1个元素的时候,假设遍历完前k个元素,使前k个元素出现在前k个位置的概率都是1/k,则遍历第k+1个元素的时候,有1/(k+1)的概率与所有k+1个元素之一交换,其出现在第k+1个位置的概率是 1 / ( k + 1 ), 其出现在前k个位置的概率是 1 / ( k + 1 ),而前面k个元素中任一个元素被交换到第k+1个位置的概率是 ( 1 - 1 / ( k + 1 ) ) / k = 1 / ( k + 1 ),而其留在前k个位置中的某一个的概率是 ( 1 - ( 1 / ( k + 1 ) ) / k = 1 / ( k + 1 ),故前k个元素在任意位置的概率都是1 / ( k + 1 )

综上所述,对任意的k,只要按照上面所述的方法,即可满足随机分布的条件。

 

一道衍生的问题,

给定一个长度未知的数据流,如果从中随机选取N个数。

 

解决方法:

1、定义一个长度为N的数组,数据流中的前N个数依次放入数组中

2、从第K( K > N )个元素开始,每个元素有N / K的概率替代数组中的任一个元素。

按这个方法进行到最后,则数据流中每个数出现在这个数组中的概率都是 1000 / N,所以这个数组中的1000个数就是解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值