问题是这样的,给一个序列,长度未知,要求从中随机等概率采样出m个元素。
最直观的解法是首先遍历序列,得到序列长度n,然后以m/n的概率从中随机取出m个元素。先不论从长度为n的序列中如何高效率的随机取出m个非重复元素,但是第一步遍历序列就使得算法时间复杂度为 O(N2) ,空间复杂度为 O(N) 。在N非常大的情况下,此种解法几乎是不可能的。
N非常大的情况对应着下面的场景:服务器持续生成着日志数据,现在需要从这些日志流中等概率选取m条数据进行分析。此情况下,上面先求序列长度的解法已不再适用(日志数据持续产生,序列长度理论上是无限的)。此时,问题转化为:对于当前生成的一条数据,以某种机制决定是否保存这条数据,使得数据被采样到的概率相等。
假设某个时间节点下已产生的序列长度为n,按以下采样策略:
- 若 n<=m ,则之前的数据需全部保留,此时数据被采样的概率均等(都为1);
- 若 n>m ,则以 m/n 的概率保留最新元素,并从已有长度为m的结果序列中随即取出一个元素与之交换,此时结果序列中的每个元素被采样到的概率都应该是 m/n ,证明如下:
- n=m+1 时,原结果序列下元素保留下来的概率为