蓄水池问题

蓄水池问题描述:

假设有N个数,从中随机抽取K个数字,如果保证抽取的过程是等概率的?其中N是不固定的

类似问题:   

                1.  从100个数字抽取20个,如果向100个数字中再增加20个呢?

                2.  给你一个长度为N的链表,N很大,但你不知道N有多大,你的任务是从这N个元素中取出K个元素,你只能遍历一次这个链表,算法保证取出的元素恰好有              

                     K个,且他们是完全随机的.

                3.  从一个不知长度的文件中随机取出K行

                4.  从实时搜索的词中随机抽出K个词

由于N是无法在抽取是确定的,但是又要保证是随机的,所以此问题需要一个特定的算法,即是蓄水池算法

                算法用代码表示如下:

                                                   

int N,K;
    void slove(int N,int K){
         int *num = new int[N];  //  num[0..K-1]存放蓄水池的元素,总共K个
         for(int i = 0;i < N;i++)
         num[i] = i+1;
         for(int i = K;i < N;i++){
              int p = rand()%K;
              if(p < K)
              swap(num[i],num[p]);        
         }
    }


                假设K = 20000,当有20001个元素时,第20001个元素被抽中的概率是20000/20001,那么前20000个元素被抽中的概率是多少呢?如果利用上面的蓄水池算法也是20000/20001,那么就符合我们的要求,下面用数学归纳法加以证明:

                蓄水池中最多放入K个元素,设定当前元素为i,当i = K+1,K+2....,N时,

                 1. 当i = K+1是,第i个元素出现在蓄水池中的概率是K/K+1,前K个元素出现在蓄水池中的概率显然也是K/K+1

                 2. 假设当j = i 时,而且第i个元素出现在蓄水池中的概率是K/i,那么前i-1个元素出现在蓄水池中的概率也是K/i

                 3. 当j = i+1时,第i+1个元素出现在蓄水池中的概率明显是K/(i+1),现在证明前i个元素出现在蓄水池中的概率也是K/(i+1)

                     前i个元素出现在蓄水池中说明 ① 在第i+1次选择前,前i个元素已经在蓄水池中②在第i+1次选择时,前i个元素没有被替换掉

                     ①由2知,前i个元素已经在蓄水池中的概率是是K/i

                     ②先考虑被替换的因素,被替换说明:第一,第i+1个元素被抽中,概率是K/(i+1);第二,有一个蓄水池元素被抽中,概率是1/K

                     那么某个元素被替换的概率是K/(i+1) * 1/K = 1/(i+1),那么前i个元素在池中且没有替换掉的概率是1-1/(i+1) =  i/(i+1)

                    综上所述,前i个元素出现在蓄水池中的概率是(K/i)*(i/(i+1))= K/(i+1).

参考文献:http://blog.youkuaiyun.com/linuxerhqt/article/details/6883785

                  陈利人  待字闺中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值