从n个数中随机选取m个

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

从n个数中随机选取m个
咋⼀看,这是个很简单的问题,但是如果n是个不确定的数呢?⽐如服务器每天会收到数以亿计的请求,但是⽬前服务器端不希望保存所有的请求,只想随机保存这些请求中的m个。

试设计⼀种算法,能够使服务器实时保存m个请求,并使这些请求是从所有请求中的⼤致等概率被选中的结果。

注意:不到⼀天的结束,是不能提前知道当天所有请求数n是多少的。

下⾯我们分两种情况讨论(1)n已知,(2)n未知。

1 n已知
可以将问题简化为:从集合A(a_1, a_2, … ,a_n),中随机选取m(0≤m≤n)个元素,使得每个数被选取的概率相等。

可以很简单的计算每个数被选取的概率是m/n。

如果集合A⾥⾯的元素本来就具有随机性,每个元素在各个位置上出现的概率相等,并且只在A上选取⼀次数据,那么直接返回A的前⾯m个元素就可以了,或者可以采取每隔k个元素取⼀个等类似的⽅法。

这样的算法局限很⼤,对集合A的要求很⾼。

假设集合A中的元素在各个位置上不具有随机性,⽐如已经按某种⽅式排序了,那么我们可以遍历集合A中的每⼀个元素a_i,根据⼀定的概率选取a_i,这个概率是多少呢,设m’为还需要从A中选取的元素个数, n’为元素a_i及其右边的元素个数,也即n’=(n-i+1)。

那么选取元素a_i的概率为 m’/n’。

这个证明较复杂,下⾯简单验证⼀下前两个元素被选中的概率:(设p(a_i=1)表⽰a_i被选中的概率,p(a_i=0)表⽰a_i没有被选中的概率)
(1)很显然p(a_1=1)=m/n
(2)p(a_2=1)= p(a_2=1,a_1=1)+p(a_2=1,a_1=0)
= p(a_1=1)*p(a_2=1│a_1=1)+ p(a_1=0)* p(a_2=1│a_1=0)
= m/n * (m-1)/(n-1) + (n-m)/n*m/(n-1)
= m/n
实际编程中选取某个元素时,可以⽣成⼀个[0,1]之间的随机数k, 若k<=m'/n'则选取这个元素,否则抛弃。

2 n未知
这个问题可以简化为:⼀个整数序列⽣成器,以⼀定时间间隔⽣成⼀个新的整数,⼀天之内会⽣成N个,希望实时保存m个整数,使得任何时刻这m个整数都是当前已⽣成的所有整数数量n中等概率抽取的结果,即概率均为m/n。

由于n是未知的,我们需要以某种特殊的⽅式进⾏判决保存还是不保存,以使得满⾜概率要求。

具体步骤如下:
(1)对于前m个请求直接保存到服务器上,对应整数序列相当于,整数数组的前m个直接存下来。

(2)对于m个以后的第k个新请求,以m/k的概率选择保存,并同从已保存的m个请求中随机选出的⼀个进⾏交换。

细说就是,
对于第m+1个请求,以m/(m+1)的概率选择留下,如果留下了则从已保存的m个请求中随机选出⼀个,同它交换;
对于第m+2个请求,以m/(m+2)的概率选择留下,如果留下了则从已保存的m个请求中随机选出⼀个,同它交换;
对于第m+3个请求,以m/(m+3)的概率选择留下,如果留下了则从已保存的m个请求中随机选出⼀个,同它交换;

下⾯我们⽤数学归纳法证明这个⽅法使每个元素被选取的概率是m/n:
(1)当n=m+1时,
对于第m+1个请求以概率m/(m+1)选择留下,显然满⾜m/n的要求;
对于前m个请求中的任何⼀个,能被选择留下有两种情况:a.第m+1个请求被选择留下了并且没有和⾃⼰进⾏交换; b.第m+1个请求没有被选择留下来⽽⾃⼰确实已被选择留下来了。

所以,概率计算为 m/(m+1) * (m-1)/m + (1 – m/(m+1)) * 1 = (m-1)/(m+1) + 1/(m+1) = m/(m+1)
(2)假设当n=N时,仍然正确,即任何⼀个请求被选中的概率都是m/N,现在推到证明当n=N+1时,任何⼀个请求被选中留下的概率是
m/(N+1)。

对于第N+1个请求,因为是以m/n=m/(N+1)的概率选中的,所以显然满⾜要求;
对于前m个请求中任何⼀个,能被选中留下同样分为同上的两种情况:a.⼀种是第N+1个被选中了但随机抽取出与它交换的不是⾃⼰; b.另⼀种情况是⾃⼰已留下并且第N+1个未被选中留下。

并且前m个请求中的某个被选中的前提是:在处理完第N个请求后,该请求被选中,根据假设这个概率是m/N。

和概率为: [ m/(N+1) * (m-1)/m + (1-m/(N+1)) ]* m/N = [ (m-1)/(N+1) + (N+1-m)/(N+1) ] * m/N = m/(N+1)。

即当n=N+1时,仍然正确。

综合1)、2)可知,此⽅法满⾜等概率要求
当然这种选取⽅法也适⽤于n已知的情况。

相关文档
最新文档