随机从长度未知的数组中抽取数字,且保证每个元素被抽到的概率相同

面试中遇到的问题,要求实现一个函数get(),从一个未知长度的数组中随机抽取一个元素,保证每个元素被抽取的概率为1/N,且空间复杂度为O(1)。解决方案是使用一个变量nVal存储抽取的数,通过一定概率存入并覆盖,最终实现每个元素被抽取的概率相等。
摘要由CSDN通过智能技术生成

昨天面试字节,手写代码之后进一步考查了一道题。面试官让我说一下有什么思路。
题目如下:

有一个函数int getNum(),每运行一次可以从一个数组V[N]里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V[N]里随机取出一个数,而这个数必须是符合1/N平均分布的,也就是说V[N]里面任意一个数都有1/N的机会被取出,要求空间复杂度为O(1)。

我当时的思路是如果随机抽取,那么肯定要用到random方法,另外如果不能获得数组长度,那么取数过程中我能用到的数据只有:当前数字的值当前数字的索引。随后就看如何构建函数保证每个数字的被取出的概率相同即可。
不过具体如何构建函数,我没有想到。
结束后,我查询了一下相关的解析如下:

  1. 设置一个整形nVal,用来存放get()返回的数。
  2. 调用getNum()从V[N]取数,按一定概率存入nVal中(覆盖以前的),直到getNum()返回NULL。
  3. 设getNum取的第i个数为nVali,nVali存入nVal中的概率为Pi。 设Pi=1/i (i已知时,所以这个概率很容易做到)。
  4. 则nVali保留,并最后返回的情况是,nVali被存入num中,且nValj(i<j<=N)不被存入nVal。
    其概率为

P(nVali)=Pi*(1- Pi+1) * (1 - Pi+2)* …(1 - PN)
=1/i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值