水库抽样

输入:一组数据,其大小未知

输出:这组数据的K个均匀抽样

要求:

  1. 仅扫描数据一次
  2. 空间复杂性为O(K)【和抽样大小有关,和整个数据量无关,不可把所有数据都放在内存里进行抽样】
  3. 扫描到数据的前n个数字时(n>K),保存当前已扫描数据的K个均匀抽样

针对此种需求,水库抽样法应运而生

算法步骤:

  1. 申请一个长度为K的数组A保存抽样
  2. 保存首先接收到的K个元素
  3. 当接收到第 i 个新元素 t 时,以 K / i 的概率随机替换A中的元素(即生成 [  1, i ]间随机数j,若 j ≤ K,则以 t 替换 A[ j ])

算法性质:

  • 该采样是均匀的。

即在任何时候,接收到的大于K的n个数据,选出来的数都保证是均匀采样。

第 i 个数据接收到的时候是以 K / i 的概率在A当中,在接收到第 i + 1的时候,第 i 个数据还能保存在A当中的概率为(1 - (1 / i+1) ),因为在接收到第 i + 1个数的时候,第 i + 1 个数要以 K/(i +1)的概率随机替换A中的元素,而元素 i 在这一步被选出来替换的概率是1/K,这两个相乘为 1 / ( i+1),便为第 i 个元素被选出的概率,所以(1 - (1 / i+1) )为在第 i+1 个元素接收到的时候,第 i 个数在数组的概率。以此类推,在第 i+2 个数到来的时候,第 i 个数仍然在数组中的概率为(1 - (1 / i+2) ),当接受到第n个数的时候,第 i 个数保存在数组的概率为(1 - (1 / n) )。只有这些事件都发生了,那么才能在接收到第 n 个数的时候,第 i 个数还保留在抽样当中,所以其保留在抽样当中的概率为这些事件相乘。

  • 空间复杂性为O(K)

在整个的算法处理当中,我们只需要一个长度为K的数组保存抽样,剩下的计算概率的啥的空间都是常数的,因此空间复杂度为O(K)

猜你喜欢

转载自blog.csdn.net/weixin_43717681/article/details/112055776