从n个数中随机选取m个
咋一看,这是个很简单的问题,但是如果n是个不确定的数呢?比如服务器每天会收到数以亿计的请求,但是目前服务器端不希望保存所有的请求,只想随机保存这些请求中的m个。试设计一种算法,能够使服务器实时保存m个请求,并使这些请求是从所有请求中的大致等概率被选中的结果。注意:不到一天的结束,是不能提前知道当天所有请求数n是多少的。下面我们分两种情况讨论(1)n已知,(2)n未知。
1 n已知
可以将问题简化为:从集合A(a_1, a_2, … ,a_n),中随机选取m(0≤m≤n)个元素,使得每个数被选取的概率相等。可以很简单的计算每个数被选取的概率是m/n。如果集合A里面的元素本来就具有随机性, 每个元素在各个位置上出现的概率相等, 并且只在A上选取一次数据,那么直接返回A的前面m个元素就可以了, 或者可以采取每隔k个元素取一个等类似的方法。这样的算法局限很大, 对集合A的要求很高。
假设集合A中的元素在各个位置上不具有随机性, 比如已经按某种方式排序了,那么我们可以遍历集合A中的每一个元素a_i,根据一定的概率选取a_i,这个概率是多少呢,设m’为还需要从A中选取的元素个数, n’为元素a_i及其右边的元素个数, 也即n’=(n-i+1)。那么选取元素a_i的概率为 m’/n’。这个证明较复杂,下面简单验证一下前两个元素被选中的概率:(设p(a_i=1)表示a_i被选中的概率,p(a_i=0)表示a_i没有被选中的概率)
(1)很显然 p(a_1=1)=m/n
(2)p(a_2=1)= p(a_2=1,a_1=1)+p(a_2=1,a_1=0)
= p(a_1=1)*p(a_2=1│a_1=1)+ p(a_1=0)* p(a_2=1│a_1=0)
= m/n * (m-1)/(n-1) + (n-m)/n*m/(n-1)
= m/n
实际编程中选取某个元素时,可以生成一个[0,1]之间的随机数k, 若k<=m'/n'则选取这个元素,否则抛弃。
2 n未知
这个问题可以简化为:一个整数序列生成器,以一定时间间隔生成一个新的整数,一天之内会生成N个,希望实时保存m个整数,使得任何时刻这m个整数都是当前已生成的所有整数数量n中等概率抽取的结果,即概率均为m/n。由于n是未知的,我们需要以某种特殊的方式进行判决保存还是不保存,以使得满足概率要求。具体步骤如下:
(1)对于前m个请求直接保存到服务器上,对应整数序列相当于,整数数组的前m个直接存下来。
(2)对于m个以后的第k个新请求,以m/k的概率选择保存,并同从已保存的m个请求中随机选出的一个进行交换。
细说就是,
- 对于第m+1个请求,以m/(m+1)的概率选择留下,如果留下了则从已保存的m个请求中随机选出一个,同它交换;
- 对于第m+2个请求,以m/(m+2)的概率选择留下,如果留下了则从已保存的m个请求中随机选出一个,同它交换;
- 对于第m+3个请求,以m/(m+3)的概率选择留下,如果留下了则从已保存的m个请求中随机选出一个,同它交换;
…
下面我们用数学归纳法证明这个方法使每个元素被选取的概率是m/n:
(1)当n=m+1时,
对于第m+1个请求以概率m/(m+1)选择留下,显然满足m/n的要求;
对于前m个请求中的任何一个,能被选择留下有两种情况:a.第m+1个请求被选择留下了并且没有和自己进行交换; b.第m+1个请求没有被选择留下来而自己确实已被选择留下来了。
所以,概率计算为 m/(m+1) * (m-1)/m + (1 – m/(m+1)) * 1 = (m-1)/(m+1) + 1/(m+1) = m/(m+1)
(2)假设当n=N时,仍然正确,即任何一个请求被选中的概率都是m/N,现在推到证明当n=N+1时,任何一个请求被选中留下的概率是m/(N+1)。
对于第N+1个请求,因为是以m/n=m/(N+1)的概率选中的,所以显然满足要求;
对于前m个请求中任何一个,能被选中留下同样分为同上的两种情况:a.一种是第N+1个被选中了但随机抽取出与它交换的不是自己; b.另一种情况是自己已留下并且第N+1个未被选中留下。并且前m个请求中的某个被选中的前提是:在处理完第N个请求后,该请求被选中,根据假设这个概率是m/N。
和概率为: [ m/(N+1) * (m-1)/m + (1-m/(N+1)) ]* m/N = [ (m-1)/(N+1) + (N+1-m)/(N+1) ] * m/N = m/(N+1)。
即当n=N+1时,仍然正确。
综合1)、2)可知,此方法满足等概率要求
当然这种选取方法也适用于n已知的情况。
【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3364139.html
从n个数中随机选取m个的更多相关文章
- 从M个数中随机选出N个数的所有组合,有序,(二)
这就是数学中的 A m n 的选取. 共有 m!/n!种可能.. 同样举一个例子吧.. 从12345这五个数字中随机选取3个数字,要求选出来的这三个数字是有序,也就是说从12345中选出来的是12 ...
- 从M个数中随机等可能的取出N个的问题
从0到m-1这m个数中随机取出n个(n<=m) 要求每个数被取到的可能性相等. 第一个方法是把这m个数丢到一个List里面 然后用nextInt(list.size())来产生随机数 然后把li ...
- javascript小实例,编写一个方法,实现从n-m个数中随机选出一个整数
别怪我是一个闷葫芦,没那么多花哨的语言,废话不多说,先说说小实例的要求: 编写一个方法,实现从n-m个数中随机选出一个整数,要求:传递的参数不足两个或者不是有效数字,返回[0-1]之间的随机数,需要解 ...
- 从python容器中随机选取元素
# 1.使用python random模块的choice方法随机选择某个元素 import random foo = ['a', 'b', 'c', 'd', 'e'] from random imp ...
- 从n个数中随机选出k个数,并判断和是不是素数
洛谷p1036 #include<iostream> #include<math.h> using namespace std; ],n,k;//依照题目所设 bool isp ...
- 从多个textarea中随机选取一个内容
<div id="IMContentTest"> <textarea name="IMContent" class="IMClass ...
- 28、周末看电影(每周五自动从top250中随机选取三部电影,并将下载链接发到邮箱里)
练习介绍 在第3关的一个课后练习里,我们爬取了指定电影的下载链接:在第6关的一个课后练习里,我们存储了豆瓣TOP250的榜单信息. 现在,我们完善这个程序,每周五在存储的榜单中,随机抽三部 ...
- js数组中随机选取一个数值!!
var arr = ["太阳光大","成功是优点的发挥","不要小看自己", "口说好话","手心向下是助人& ...
- 面试中常问的有关随机选取k个数的总结
1.在半径为1的圆中随机选取一点. 2.给定一个未知长度的整数流,如何随机选取一个数 3.给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字).如何才能从这个无穷尽的流 ...
随机推荐
- 在ASP.NET MVC中使用typeahead.js支持预先输入,即智能提示
使用typeahead.js可以实现预先输入,即智能提示,本篇在ASP.NET MVC下实现.实现效果如下: 首先是有关城市的模型. public class City { public int Id ...
- Delphi的自动编译软件Want
Delphi自动编译环境的搭建及使用 什么是Want Want是一套Windows下用于编译Delphi源代码的工具.Want的名称是Windows Ant的意思. Ant是Java下最著名的自动编译 ...
- java根据模板文件导出pdf
原文:https://www.cnblogs.com/wangpeng00700/p/8418594.html 在网上看了一些Java生成pdf文件的,写的有点乱,有的不支持写入中文字体,有的不支持模 ...
- UITableView分割线样式与颜色
tv.separatorStyle = UITableViewCellSeparatorStyleSingleLine; //设置样式 tv.separatorColor = [UIColor c ...
- C#编程(五十六)----------可观察的集合ObservableCollection
原文链接: http://blog.csdn.net/shanyongxu/article/details/47080685 可观察的集合 如果需要集合中的元素核实删除或添加的信息,就可以使用Obse ...
- 11i and R12 Table Count in Different Module
Advertisement Module 11i Tables R12 Tables New Tables AR 551 616 118 BOM 264 337 73 GL 186 309 140 A ...
- java 日历类Calendar用法
如何获取昨天?取昨天的日期,本想的截出来日期减一就好了.又一想不对,如果今天是一号怎么办? 现有两个办法 1: Date as = new Date(new Date().getTime()-24*6 ...
- whl文件(python)安装方法
https://blog.csdn.net/fhl812432059/article/details/51745226 windows7 python2.7 1.用管理员方式打开cmd 2.首先通过p ...
- 【BZOJ】【4152】【AMPZZ2014】The Captain
最短路 题解:http://zyfzyf.is-programmer.com/posts/97953.html 按x坐标排序,相邻点之间连边.满足dist(x1,x3)<=dist(x1,x2) ...
- RateLimiter
RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类. 限流算法 常用的更平滑的限流算法有两种:漏桶算法和令牌桶算法. 很多传统的服务提供商如华为中兴都有类似的专利, ...