首页 > 试题广场 >

为分析用户行为,系统常需存储用户的一些query,但因que

[问答题]
为分析用户行为,系统常需存储用户的一些query ,但因query 非常多,故系统不能全存,设系统每天只存mquery ,现设计一个算法,对用户请求的query 进行随机选择m 个,请给一个方案,使得每个query 被抽中的概率相等,并分析之,注意:不到最后一刻,并不知用户的总请求量。
推荐

思路:如果用户查询的数量小于m,那么直接就存起来。如果用户查询的数量大于m,假设为m+i,那么在1-----m+i之间随机产生一个数,如果选择的是前面m条查询进行存取,那么概率为m/m+i),如果选择的是后面i条记录中的查询,那么用这个记录来替换前面m条查询记录的概率为m/m+i*1-1/m=(m-1)/(m+i),当查询记录量很大的时候,m/m+i== (m-1)/(m+i),所以每个query被抽中的概率是相等的。

编辑于 2015-02-09 00:34:38 回复(0)
大致伪代码如下:
int count = 1;
string query[m+1]; //为了方便理解,从1开始存
while(scanf("%s",&cur_query)!=EOF) {
      count++;
      if(count <= m) {  // 如果输入小于m,直接存。
         query[count] = cur_query;
      } else {  // 剩余的,就随机一个数,并交换。具体为何,在下述证明可见
         int M = random(1, count);
         if( M < m) {
             query[M] = cur_query;
         }
}

证明每个query被抽中的概率相等:(假设总请求量为N)
1. 如果N<=m,每个query都被存下来,那么query被抽中保存下来的概率均为1.所以相等
2. N > m. 将query分成前m个和后m个来看(其实也就对应伪码中if/else 两种处理方式)
  • 对于第i个数(i < m),在前m步被选中的概率仍是1.但是从第m+1步,i就有可能被替换掉,被替换掉的概率是 1/count。第m+1步,count = m+1,所以不被替换的概率为m/m+1。接下来的也就是m+1/m+2、m+2/m+3 。 那么读到第N个数时, 显然第i个数被选中的概率 = 每一步都不替换的概率,即  m/m+1 * m+1/m+2  n-1/n = m/n
  • 对于第i个数(i >= m)时。要想被选中的概率为,首先,在它出现的那一次,M取值要<k,这个概率就是m/count. 接下来每一步都不被替换的计算过程跟上面一样。所以此时第i个数被选中的概率 = m/count * count /count+1 。。。n-1/n = m/n
所以用这种方法,概率是相同的。
发表于 2015-03-26 22:13:00 回复(1)
首先把前m个query拿出来放入m个槽中。
之后没遇到一个新的query就使用当前query总数n计算保留概率m/n。
如果决定保留,那么在m个槽中随机选择一个槽进行替换。
每次替换时,新query的保留概率为m/n,旧quer保留概率是m/(n-1)*m/n*(m-1)/m+(n-m)/n*m/(n-1) 。
大家可以把数值带进去看比较容易理解。
发表于 2017-10-02 01:36:15 回复(0)
不会
发表于 2015-10-27 11:19:44 回复(0)
蓄水池抽样
发表于 2014-10-11 17:37:09 回复(0)
经典概率题目,google面试的时候被问到过。
发表于 2014-10-10 10:37:13 回复(0)