蓄水池算法

问题:

如何从N个元素中等概率抽取K个元素(N > K)

方法:

首先构建一个可放k个元素的蓄水池,将序列的前k个元素放入蓄水池中,然后从第k+1个元素开始,以k/i (k<i<=n)的概率来决定该元素是否被替换到池子中,并且从池子中等概率淘汰一个球。

    1. 对于第i个数(i<k),在前k步被选中的概率是1, 从第k+1步开始,i不被选中的概率为k/k+1,那么读到第n个数时, 第i个数(i<k)被选中的概率 = 被选中的概率 * 以后每一步都不被换走的概率,即
      1 * k/k+1 * k+1/k+2 n-1/n = k/n
    2. 对于第j个数(j>=k)被选中的概率为: 在他出现时被选中的概率 * 在他出现以后不被换走的概率,即: 
      k/j * j /j+1 。。。n-1/n = k/n
    3. 综上得证。

应用:

玩家登陆的那一刻即可知道是否中奖,不用等到收集完所有上线玩家,且只需维护一个中奖池而不是一个玩家池。

时间: 2024-10-11 22:39:49

蓄水池算法的相关文章

蓄水池算法介绍和证明[原创]

蓄水池算法要解决的问题就是在不知道流入数据量多少的情况下,依旧可以随机从这些数中选取K个,乍一听好神奇,其实分析一下背后的概率知识,思想还是很简单的,相信看完我的介绍和证明,你也会觉得很简单. 假设要求随机选择K个元素,假设一共流入的元素有n个. 首先数组a[0...k-1]表示最后返回的结果,最开始流入的k个元素依次放入a[0...k-1]中: 那么从第k+1到第n个元素每一次都有可能把数组a中的元素踢走换成自己,假设现在流入了第i个元素,搞个随机数生成器,pos=rand()%i,如果pos

[程序员代码面试指南]第9章-蓄水池算法

题目描述 从N个元素中随机抽取k个元素,但的k个数无法事先确定. 在实际应用中,往往会遇到很大数据流的情况.因此,我们无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一遍就得到所选取的元素,并且保证得到的元素是随机的算法. 特别地,此题元素为1-N. 解题思路 蓄水池算法. 先选取个元素中的前k个元素,保存在集合中: 从第i(i>k)个元素开始,每次先以k/i概率选择是否让第i个元素留下.若第i个元素存活,则从集合中k个元素随机扔掉一个,并将该元素放入集合:否则直接扔掉该元素: 重

蓄水池算法简介

长度为N的数据流,要从中随机取得k个数据,N很大(可能大于你的内存和磁盘容量)且未知,只能遍历一次,求怎样可以取得完全随机的k个数据. 方法为: 1.定义一个长度为k的数组存储前k个数据 2.数据流流动,当输入的数据流的数据数量为i(k<i<N)时,取一个1到i的数字,如果生成的数字小于k,则把这个数字所对应的数组内的数字与i上的数进行交换. 完成这两步之后便可以实现在长度为N的数据流中取出k个随机数的目的了. 接下来将会证明对于N个数据,每个数据被取到的概率均为k/N. 证明: 采取数学归纳

概率/随机数算法

0-1等概率问题 问题描述 一个随机数产生器以概率P生成0,以概率(1-P)生成1,怎样生成等概率的0和1? 主要思路 如果用这个产生器产生两个位,出现00的概率为P^2,出现01的概率为P(1-P),出现10的概率为P(1-P),而出现11的概率为(1-P)^2.故而可以用10表示1,01表示0,从而保证生成0和1的概率是相同的. 代码实现 int generate01(int (*func)()) { if (func == NULL) return -1; int num1 = -1; i

蓄水池采样问题

问题描述 要求从N个元素中随机的抽取k个元素,其中N无法确定.例如: 从 100000 份调查报告中抽取 1000 份进行统计. 从一本很厚的电话簿中抽取 1000 人进行姓氏统计. 从 Google 搜索 "Ken Thompson",从中抽取 100 个结果查看哪些是今年的. 这种应用的场景一般是数据流的情况下,由于数据只能被读取一次,而且数据量很大,并不能全部保存,因此数据量N是无法在抽样开始时确定的:但又要保持随机性,于是有了这个问题. 算法思想 假设数据序列的规模为 n,需要

程序员代码面试指南 IT名企算法与数据结构题目最优解 ,左程云著pdf高清版免费下载

下载地址:网盘下载 备用地址:网盘下载 内容简介  · · · · · ·这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮助广大程序员的面试准备做到万无一失.“刷”完本书后,你就是“题王”!__eol__本书采用题目+解答的方式组织内容,并把面试题类型相近或者解法相近的题目尽量放在一起,读者在学习本书时很容易看出面试题解法之间的联系,使知识的学习避免碎片化

[总结]随机抽样与蓄水池抽样问题

现实中碰到很多需要随机抽样的问题,这也是算法工程师面试中常见的题型,特意记录在这里.下面以几个例题为例,展开随机抽样问题的解决方案. [leetcode]470.Implement Rand10() Using Rand7() 已提供一个Rand7()的API可以随机生成1到7的数字,使用Rand7实现Rand10,Rand10可以随机生成1到10的数字.可以通过拒绝采样的方法来计算:用Rand49生成一个数,如果它位于41-49,则丢弃,继续生成,当生成一个1-40的数时返回.这样子做可以近似

MySTL:蓄水池抽样算法

给你一个长度为N的链表.N很大,但你不知道N有多大.你的任务是从这N个元素中随机取出k个元素.你只能遍历这个链表一次.你的算法必须保证取出的元素恰好有k个,且它们是完全随机的(出现概率均等). 这一题应该可以用来解决微信红包分配之类的那种问题,主要是概率的证明挺有意思. 1 #include <iostream> 2 #include <algorithm> 3 #include <time.h> 4 5 using namespace std; 6 7 typedef

Twitter面试题蓄水池蓄水量算法(原创 JS版,以后可能会补上C#的)

之前在群里有人讨论Twitter的面试题,蓄水池蓄水量计算,于是自己写了个JS版的(PS:主要后台代码还要编译,想想还是JS快,于是就使用了JS了.不过算法主要还是思路嘛,而且JS应该都没问题吧^_^;) 这里是题目: ---------------------------分割线------------------------ 蓄水池储水量问题 看图,可以将方块看做砖.题干很简单,问最多能放多少水.例如,图2就是图1可放的最多水(蓝色部分),如果将一块砖看做1的话,图2就是能放10个单位的水.图