原题:为分析用户行为,系统常需存储用户的一些query,但因query非常多,故系统不能全存,设系统每天只存m个query,现设计一个算法,对用户请求的query进行随机选择m个,请给一个方案,使得每个query被抽中的概率相等,并分析之,注意:不到最后一刻,并不知用户的总请求量。
这道题很有趣。来看看怎么做。
这题的一个关键是,由于我们不知道query有多少个,也就是说,我们根本不知道query什么时候突然就没有了!
所以,我们要保证,任何时刻,我们手上拿着的那m个query,都是等可能的。这个特点,再次启发我们使用递归的思路。
假设现在我们手上拿着m个query,并且在过去我们已经累积接受过n-1个query了。现在又来了一个query,它是第n个,我们把它叫做X
由归纳假设,在这个X来之前,我们手上的m个query是等可能被选中的,我们设这个概率为t。
现在,对于这个新来的X,我们有两种选择,我们要么就抛弃它,要么就把它加进来,并且抛弃原来的m个query里的某一个。
那么,算法的原型就出来了:
对于这个X,我们有两种选择:
1. 以概率p抛弃X,原来的m个query不变
2. 以概率1-p保留X,并且将原来的m个query里的任意一个等可能地抛弃,最后得到一个新的m组合
现在要分析这个p到底怎么算出来。
先确定样本空间,这里的样本空间,是n选m的一个组合。
对于情况1,每个样本点对应的概率应该是 t * p,这个比较显然。
情况2的分析就要复杂一点。
考察某个样本点b[1..m],其中b[m] = X。这个样本点出现的概率是多少呢?
为了让这个样本点出现,我们要把X加进来,然后抛弃原来的m个数里的某一个(我们把它叫做Y)。
举个例子来说吧,假设现在的n = 99, m = 5,X = 99,我们手上的m个数是 5,6,15,50, 99
在我们加入这个99之前,原来的m个数可能的情况是:
{1,5,6,15,50}, {2,5,6,15,50} 。。。。 {5,6,15,50,98}
一共有 98 - 4 = 94种,也就是 (n - 1) - (m - 1) = n - m 种
而且,这些情况出现的概率都是t,所以,对于某个特定的样本点,出现的概率是 t * (1-p) * (1/m) * (n - m)
显然,一个合理的p必须满足:
t * p = t * (1-p) * (1/m) * (n - m)
把p解出来,算法就完成了就行了。