从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.给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字).如何才能从这个无穷尽的流 ...
随机推荐
- 安装/使用 MVVMLight(转)
安装 MVVMLight Toolkit 为什么说是 MVVMLight Toolkit ?实际上我们一般安装的都是 MVVMLight Toolkit ,这个里面包含了工具就是在VS新建工程的时候你 ...
- Nginx 的动态 upstreams
原文地址: http://www.oschina.net/translate/nginx-with-dynamic-upstreams 我最近在工作中做一个设置,我有一个面向用户的 Nginx 服务, ...
- 迭代dict的key和value
我们了解了如何迭代 dict 的key和value,那么,在一个 for 循环中,能否同时迭代 key和value?答案是肯定的. 首先,我们看看 dict 对象的 items() 方法返回的值: & ...
- 【elasticsearch】关于elasticSearch的基础概念了解【转载】
转载原文:https://www.cnblogs.com/chenmc/p/9516100.html 该作者本系列文章,写的很详尽 ================================== ...
- React中的的JSX
什么是JSX? JSX是JavaScript XML的缩写,其本质是js,表现形式类似于XML,与js区别在于可直接在里面编写html标签. 怎么使用JSX? 语法规则: JSX 的基本语法规则:HT ...
- SharePoint Online 创建文档库
前言 本文介绍如何在Office 365中创建文档库,以及文档库的一些基本设置. 正文 通过登录地址登录到Office 365的SharePoint Online站点中,我们可以在右上角的设置菜单中, ...
- TX1 flash backup & restore
备份:耗时2.5小时 ./tegraflash.py --bl cboot.bin --applet nvtboot_recovery.bin --chip 0x21 --cmd "read ...
- 【周年庆】china-pub 14周年庆感恩回馈四波狂热来袭
活动主题:china-pub 14周年庆感恩回馈四波狂热来袭活动说明:[第1波]电子书免费抢!10万好书 65折封顶! 活动规则: 1.活动期间内凡 ...
- modbus.c
#include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> //#include ...
- [转]PHP中替换换行符
FROM :http://www.cnblogs.com/siqi/archive/2012/10/12/2720713.html //php 有三种方法来解决 //1.使用str_replace 来 ...