昨天晚上参加了喜马拉雅的笔试,看完这题我一脸愣逼,当时的第一个想法是类似线段树,每次从m个数中随机一个数进入到上一层。。。最后发现要保证等概率的问题对长度实质是由要求的。
回去果断百度,发现这题其实在11年的百度笔试题中就出现过,惭愧。
原题大概是这样的:
一个服务器一天内会收到很多request,但是服务器只能存放m个request,试设计一种算法并证明,使得在时时的reqest中选择m个保存,并保证最后各个request被选中的概率为大致相同。记住,不到最后,不知道request的总数n。
解题方案:
首先将前m个request依次放入服务器的大小为m的备选集合中,当第m+1个来临时,利用轮盘算法来保证第m+1个有m/(m+1)的概率能够进入到备选集合中,如果满足进入条件再将备选集合中m个request中等概率选择一个替换进行替换。当第m+i个来临时,有
m/(m+i)的概率能够进入到备选集合中,并在已保存的m个request中等概率选择一个替换之。 依次类推,第N个request以m/N的概率被选择,并在已保存的m个request中等概率选择一个替换之。最终每个request被选择的概率为m/n。
证明:
当N=m+1时,第m+1个选中的概率为m/(m+1);
而第i个(i <= N)被选中的概率为:第N个没有机会进入到集合中的概率+第N个进入到集合中的概率*第i
个数据不会被替换掉的概率。
得:1/(m+1) + m/(m+1) * (m-1)/m = m/(m+1);
假设当N = n时,每个request被选择的概率为m/n;
那么接下来我们只需要证明当N = n+1时,每个request被选择的概率为m / (n+1),即可.
第n+1个选中的概率为m/(n+1);
此时第i个(i <= N)request被选择的概率为:在N = n时,第i个能够被保留下来的概率* (第n+1个没有机会进入到集合中的概率+第n+1个进入到集合中的概率*第i
个数据不会被替换掉的概率)。
得:(m/n)* ( (n+1-m)/(n+1) + m/(n+1) * (m-1)/m )= (m / n)*(n/(n+1))= m/(n+1)。
证毕。