百度笔试题目:为分析用户行为,系统常需存储用户的一些query,但因query非常多,故系统不能全存,设系统每天只存m个query,现设计一个算法,对用户请求的query进行随机选择m个,请给一个方案,使得每个query被抽中的概率相等,并分析之,注意:不到最后一刻,并不知用户的总请求量。
方法一:
前m个直接存
对后面来的每个数据a[i](i > m),
随机生成一个(1..i)之前的随机数x,
若x<=m,确定a[i]被选中;再随机生成(1..m)之间的随机数y,用a[i]替换a[y].
证明思路:
1)对于处理前m个数,大家都被保存,概率都相等且为1
2)对于第i(i>m)个数a[i],被选中的概率是m/i;
对于之前保存的m个数,它们每一个上一次存活下来的概率是m/(i - 1)[从i-1个数中选m个数],本次存活的概率是1-(m/i)*(1/m)=1-1/i,所以到当前为止被选中概率是两者相乘=m/i
得证。
下面两个方法是从Hackbuteer1
http://blog.csdn.net/hackbuteer1/article/details/7971328
里面看来的,仅仅简化了一下证明流程。
方法二:
给每个元素随机生成一个固定区间(如[0,1])的权重。用一个大小为m的堆来选取权重较大的m个元素。
方法三:
前m个直接存
对后面来的每个数据a[i](i > m),
随机生成一个(1..i)之前的随机数x,
若x<=m,确定a[i]被选中,用a[i]替换a[x];
证明思路:
1)对于处理前m个数,大家都被保存,概率都相等且为1
2)对于第i(i>m)个数a[i],被选中的概率是m/i;
对于之前保存的m个数,它们每一个上一次存活下来的概率是m/(i - 1),本次存活的概率是1-1/i,所以到当前为止被选中概率是两者相乘=m/i
得证。