随机算法

1. 要求从N个元素中随机的抽取1个元素。


2. 要求从N个元素中随机的抽取K个元素。

复制代码
int remain = N
int select = K
for (int i = 0; i < N; ++i){
   
if (rand()% remain < select){
      cout
<<i<<" ";
      
--select;
   }
   
--remain;
}
复制代码

 

第一个元素被选中的概率为 K/N

第二个元素被选中的概率为(K/N)*((K-1)/(N-1)) + ((N-K)/N) * (K/(N-1)) = K/N

.........

证明略(参看The Art of Computer Programming III)


3. 要求从N个元素中随机的抽取1个元素, 其中N无法确定(数据流)。

复制代码
int Num;
int i = 0;
int choose = 0;
while(scanf("%d"&Num)&& Num != 0){
   
if (((double)rand()/(double)RANDOM_MAX) < (1.0 / (double)++i))
      choose 
= Num;
}
cout 
<< choose <<endl;
复制代码


总是选择第一行, 二分之一几率选择第二行, 以此类推, K分之一机率选择第K行, 当while 执行完毕,假设N个数字,则每个数字被选择的机率均为1/N

第一行被选择的机率为:

1 * 1/2 * 2/3 * 3/4 *.... (N-1)/N = 1/N

第K行被选择的机率为:

1/K * K/(K+1) * .... (N-1)/N = 1/N


4. 要求从N个元素中随机的抽取K个元素, 其中N无法确定(数据流)。

reservoir sampling

//Init : a reservoir with the size: K
for(int i = K; i < N; ++i){
   
int M = rand() % i;
   
if( M < K)
      SWAP the Mth value and ith value
}


解决方案就是蓄水库抽样(reservoid sampling)。主要思想就是保持一个集合(这个集合中的每个数字出现),作为蓄水池,依次遍历所有数据的时候以一定概率替换这个蓄水池中的数字。

(1)初始情况。出现在水库中的k个元素的出现概率都是一致的,都是1。这个很显然。

(2)第一步。第一步就是指,处理第k+1个元素的情况。分两种情况:元素全部都没有被替换;其中某个元素被第k+1个元素替换掉。

我们先看情况2:第k+1个元素被选中的概率是k/(k+1)(根据公式k/i),所以这个新元素在水库中出现的概率就一定是k/(k+1)(不管它替换掉哪个元素,反正肯定它是以这个概率出现在水库中)。下面来看水库中剩余的元素出现的概率,也就是1-P(这个元素被替换掉的概率)。水库中任意一个元素被替换掉的概率是:(k/k+1)*(1/k)=1/(k+1),意即首先要第k+1个元素被选中,然后自己在集合的k个元素中被选中。那它出现的概率就是1-1/(k+1)=k/(k+1)。可以看出来,旧元素和新元素出现的概率是相等的。

情况1:当元素全部都没有替换掉的时候,每个元素的出现概率肯定是一样的,这很显然。但具体是多少呢?就是1-P(第k+1个元素被选中)=1-k/(k+1)=1/(k+1)。

(3)归纳法:重复上面的过程,只要证明第i步到第i+1步,所有元素出现的概率是相等的即可。参见:http://wansishuang.javaeye.com/blog/443902


5. Shuffle (Fisher–Yates shuffle)

复制代码
void shuffle(int cards[], int n){
    
while (n > 1){
        
// Swap a random unshuffled card with the top-most card
        int k = rand() % n--;
        swap(cards[n], cards[k]);
    }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值