为分析用户行为,系统常需存储用户的一些query,但因query非常多,故系统不能全存,设系统每天只存m个query,现设计一个算法,对用户请求的query进行随机选择m个,请给一个方案,使得每个query被抽中的概率相等,并分析之,注意:不到最后一刻,并不知用户的总请求量。
做法:
1、如果query总数小于等于m,直接存起来。
2、如果query数目开始大于m,例如为m+i个,那么从m+1,……m+i,每个新来的query元素m+k(k=1……i),用m/(m+k)的概率去取,即可用m+k的随机数来判别。
3、如果随机数判定该query元素被取中,那么对已存好的m个元素,每个元素均用1/m的概率去判定是否被m+k替换,例如原先m=5,{1,2,3,4,5},当前m+k为6,对1,2,3,4,5每个都有1/5的概率被替换成6即m+k。
4、如果m+k没被选中,则考察m+k+1个元素,继续判别m+k+1是否被取中,取中则执行3,否则继续判别下一个元素。直到m+1……m+k个元素全部被考察替换完毕。
关键点,每个query抽中概率相等,言下之意是指每次多来一个query的时候,这个新来的query和已经有的query被抽取放入存储区的概率都应该要相等。前m个,每个取的概率均为1,这相等。从m+1开始,取的概率为m/(m+1),那么前面m个query被取放入存储区的概率=1-被第m+1个query替换的概率=1-m/(m+1)*(1/m)(即m+1被取中且刚好用1/m的概率替换掉存储区中的某元素)=m/(m+1)符合条件。
假设m+p成立,即m+p被取的概率为m/(m+p),则m+p+1的被取概率P1为m/(m+p+1),存储区中的元素被取的概率P2=被取中且没有被m+p+1替换=(首先在m+p的时候要被取)*((m+p+1)没取中+(m+p+1)取中但是没替换掉自己)=m/(m+p)((1-m/(m+p+1))+m/(m+p+1)(1-1/m))=m/(m+p+1)
P1==P2,所以每个query的抽取放入存储区中的概率一样。
参考了http://blog.csdn.net/hackbuteer1/article/details/7971328这篇博文的解释。
主要是写下了具体的操作思路,以作备忘,如有错漏,请不吝指教