从输入流中随机抽取m个元素

从输入流中随机抽取k个元素

有一个很大很大的输入流,大到没有存储器可以将其存储下来,而且只输入一次,如何从这个输入流中随机取得m个记录。

思路:

我们可以用Fisher-Yates随机排列算法解决该问题。用大小为m的数组arr[0:m-1]来保存随机抽取的元素,arr[0:m-1]逐步初始化为输入流的前m个元素的一个随机排列。

对于输入流中的第k (k>m)个元素,随机生成一个[0,k-1]区间内的整数i,如果此随机整数i小于等于m,那么就用第k个元素覆盖掉arr[i-1],否则,丢弃第k个元素。

注意,每从输入流中提取一个新元素,我们都要随机生成一个整数,而此整数的有可能出现的范围都要加1. 

http://peizhyi.iteye.com/blog/1434391 给出的算法是错误的,这个算法有两个问题:

  • 随机流的大小未知,所以所谓的“假设有n条记录”是不成立的;
  • 即便随机流的大小是n,但是每次从[0,n-1]的范围随机生成一个整数,将此整数作为元素在arr中的位置,这样找出的m个元素并非等概率的m个元素。
为什么http://peizhyi.iteye.com/blog/1434391 给出的算法不能生成一个等概率的抽取呢?原因很简单:由于数组arr被初始化为输入流的前m个元素,前m个元素是以100%的概率被插入到数组arr中的。但是,对于输入流中往后的元素,如果从[0,n-1]中随机生成它们的位置,显然它们只能以m/n的概率被插入到数组arr中,用这种方式生成的随机抽取显然就不是等概率的了。

相关问题:从二叉树上随机抽取1个节点


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值