问题描述

一个文件中含有n个元素,只能遍历一遍,要求等概率随机取出其中之一。

    先讲一个例子,5个人抽5个签,只有一个签意味着“中签”,轮流抽签,那么这种情况,估计这5个人都不会有异议,都觉得这种方法是公平的,这确实也是公平的,“抓阄”的方法已经有很长的历史了,要是不公平的话老祖先们就不干了。

    或许有人觉得先抓的人中签的概率会大一些,因为要是前面的人中了,后面的中签概率就是0了,也可能有人会觉得后面抓的人更有优势,因为前面拿去了不中的签,后面中签的概率就大,那么我们就计算一下吧。

问题分析

    第一个人中签的概率是1/5,

    第二个人中签的情况只能在第一个人未中时才有可能,所以他中的概率是4/5 X 1/4 = 1/5(4/5表示第一个人未中,1/4表示在剩下的4个签里中签的概率),所以,第二个人最终的中签概率也是1/5,

    同理,第三个人中签的概率为:第一个人未中的概率X 第二个人未中的概率X第三个人中的概率,即为:4/5 X 3/4 X 1/3 = 1/5,

    一样的可以求出第四和第五个人的概率都为1/5,也就是说先后顺序不影响公平性。

    说这个问题是要说明这种前后有关联的事件的概率计算的方式,我们回到第1个问题。前几天我的一个同学电面百度是被问到这个问题,他想了想回答说,依次遍历,遇到每一个元素都生成一个随机数作为标记,如果当前生成的随机数大于为之前保留的元素生成的随机数就替换,这样操作直到文件结束。

    但面试官问到:如果生成的随机数和之前保留的元素的随机数一样大的话,要不要替换呢?

    你也许会想,一个double的范围可以是-1.79E+308 ~ +1.79E+308,要让两个随机生成的double相等的概率不是一般的微乎其微啊!但计算机世界里有条很让人伤心的“真理”:可能发生的事件,总会发生!

    那我们遇到这种情况,是换还是不换?To be or not to be, that’s a question!

    就好比,两个人百米赛跑,测出来的时间一样,如果只能有一个人得冠军的话,对于另一个人始终是不公平的,那么只能再跑一次,一决雌雄了!

我的策略

    下面,说一个个人认为比较满足要求的选取策略:

  •  顺序遍历,当前遍历的元素为第L个元素,变量e表示之前选取了的某一个元素,此时生成一个随机数r,如果r%L == 0(当然0也可以是0~L-1中的任何一个,概率都是一样的), 我们将e的值替换为当前值,否则扫描下一个元素直到文件结束。

    你要是给面试官说明了这样一个策略后,面试官百分之一千会问你这样做是等概率吗?那我们来证明一下。

证明

     在遍历到第1个元素的时候,即L为1,那么r%L必然为0,所以e为第一个元素,p=100%,

    遍历到第2个元素时,L为2,r%L==0的概率为1/2, 这个时候,第1个元素不被替换的概率为1X(1-1/2)=1/2,

     第1个元素被替换,也就是第2个元素被选中的概率为1/2 = 1/2,你可以看到,只有2时,这两个元素是等概率的机会被选中的。

    继续,遍历到第3个元素的时候,r%L==0的概率为1/3,前面被选中的元素不被替换的概率为1/2 X (1-1/3)=1/3,前面被选中的元素被替换的概率,即第3个元素被选中的概率为1/3

    归纳法证明,这样走到第L个元素时,这L个元素中任一被选中的概率都是1/L,那么走到L+1时,第L+1个元素选中的概率为1/(L+1), 之前选中的元素不被替换,即继续被选中的概率为1/L X ( 1-1/(L+1) ) = 1/(L+1)。证毕。

    也就是说,走到文件最后,每一个元素最终被选出的概率为1/n, n为文件中元素的总数。

 posted on 2012-11-30 20:10  husterchenji  阅读(450)  评论(0编辑  收藏  举报