随机从长度未知的数组中抽取数字,且保证每个元素被抽到的概率相同
昨天面试字节,手写代码之后进一步考查了一道题。面试官让我说一下有什么思路。
题目如下:
有一个函数int getNum(),每运行一次可以从一个数组V[N]里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V[N]里随机取出一个数,而这个数必须是符合1/N平均分布的,也就是说V[N]里面任意一个数都有1/N的机会被取出,要求空间复杂度为O(1)。
我当时的思路是如果随机抽取,那么肯定要用到random
方法,另外如果不能获得数组长度,那么取数过程中我能用到的数据只有:当前数字的值
及当前数字的索引
。随后就看如何构建函数保证每个数字的被取出的概率相同即可。
不过具体如何构建函数,我没有想到。
结束后,我查询了一下相关的解析如下:
- 设置一个整形nVal,用来存放get()返回的数。
- 调用getNum()从V[N]取数,按一定概率存入nVal中(覆盖以前的),直到getNum()返回NULL。
- 设getNum取的第i个数为nVali,nVali存入nVal中的概率为Pi。 设Pi=1/i (i已知时,所以这个概率很容易做到)。
- 则nVali保留,并最后返回的情况是,nVali被存入num中,且nValj(i<j<=N)不被存入nVal。
其概率为
P(nVali)=Pi*(1- Pi+1) * (1 - Pi+2)* …(1 - PN)
=1/i * (i/(i+1)) ((i+1)/(i+20)…((N-1)/N) = 1/N
由于我们这里无法获得N的长度,所以我们可以用生成的随机数对当前索引i取余数,来保证结果的随机性(其实我这里并不是特别的理解)。改写成对应C++的代码如下
int GetRand()
{int i=1;int nRet = 0;int nVal = 0;while((nRet=getNum())!=NULL){if(rand()%(i++)==0) nVal = nRet;}return nVal;
}
由于我的主语言是Python,所以我尝试把这段代码改写成Python。比较尴尬的一点是,Python中的随机数只能在某一个范围内生成(即不可能生成一个无限大的数字)。这样,我们需要构建一个新的字符来统计当前出现过的最大值。这样我写出的代码如下:
nums = [2,3,1,4,5,6,8,7,9]import random
i = 1
val = 0
Max = 0
while nums:n = nums.pop()#统计当前数组中出现的最大值Max = max(n,Max)if random.randint(0,Max) % i == 0:val = ni += 1print(val)
如此就可以实现上述功能啦!
随机从长度未知的数组中抽取数字,且保证每个元素被抽到的概率相同相关推荐
- 【宫水三叶的刷题日记】961. 在长度 2N 的数组中找出重复 N 次的元素
题目描述 这是 LeetCode 上的 961. 在长度 2N 的数组中找出重复 N 次的元素 ,难度为 简单. Tag : 「模拟」.「计数」.「构造」.「哈希表」 给你一个整数数组 nums ,该 ...
- java中数组的下标比较_【Java】 剑指offer(53-3) 数组中数值和下标相等的元素
本文参考自<剑指offer>一书,代码采用Java语言. 题目 假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程实现一个函数找出数组中任意一个数值等于其下标的元素.例如,在数 ...
- 215. 数组中的第 K个最大元素
215. 数组中的第 K个最大元素 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数 组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5 ...
- LC215. 数组中的第K个最大元素
题目介绍 数组中的第K个最大元素 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素. 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 输入: [ ...
- 对数组中的数字 1 和 2 进行排序,使得数字 1、2 分别位于前、后部分
问题描述:假设某个数组中只有数字 1 和 2,进行排序,使得数字 1 位于数组前部分,数字 2 位于后部分. 这道算法题其实不是很难,使用各种排序算法应该都能解出,但是若要考虑性能问题,那就得选择一种 ...
- 数组中的第K个最大元素
数组中的第K个最大元素 在未排序的数组中找到第k个最大的元素.请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素. 示例 输入: [3,2,1,5,6,4] 和 k = 2 输出 ...
- LeetCode——215,数组中的第K个最大元素(分治法)
尹成老师带你学算法 /*** \* Created: liuhuichao* \* Date: 2020/1/27* \* Time: 11:32 上午* \* Description: 数组中的第K ...
- 力扣(LeetCode)215. 数组中的第K个最大元素(C语言)
一.环境说明 本文是 LeetCode 215题 : 数组中的第K个最大元素,使用c语言实现. 快速选择.查找无序数组的利器! 测试环境:Visual Studio 2019. 二.代码展示 void ...
- 【Dart 教程系列第 6 篇】Dart 之 addAll 合并两个数组(向数组中一次添加多个元素)
这是[Dart 教程系列第 6 篇],如果觉得有用的话,欢迎关注专栏. Dart 合并两个数组,或者说是向数组中一次添加多个元素,可以使用 addAll() 方法. 该方法无返回值,参数类型为 Ite ...
最新文章
- AngularJS ng-if使用
- 血亏 1.5 亿、华为断供、Linux 之父怒删代码,2020 IT 大事记盘点
- vs2010 失效后的解决办法
- Linux文件目录及其作用
- Redis中的客户端重定向
- Intellij idea 快键键
- 面试官系统精讲Java源码及大厂真题 - 01 开篇词:为什么学习本专栏
- Android中文API(128) —— HandlerThread
- mysql的事务与锁机制
- Bootstrap3 Affix插件
- android 解压zip报错_Android 使用 Batterystats 和 Battery Historian 分析电池用量
- sql查询条件为空的另类写法o( ̄▽ ̄)d
- flex-direction css3属性设定弹性盒子模型子元素反向排列
- 深度学习: marginal cost (边际成本)
- 安卓从入门到进阶第一篇(环境搭建)
- ABAP 企业微信ASE 加密算法
- 一种自动将3DMax模型转换为UE4直接可用的模型资源的方法与流程
- Vue路由守卫(导航守卫)及使用场景
- Android动画了解—一些项目案例分析
- iOS15上最受欢迎的功能,居然是“我想静静”?
热门文章
- autojs安卓10,11泡椒云提示无法读取imei码解决方案
- 单目三维目标检测之CaDDN论文阅读
- 12枚硬币中取1枚假币的问题
- 画风突变!用友云全新定义数字企业智能服务
- php网页无痕预览,javascript,html5_如何应对用户使用无痕浏览模式,javascript,html5 - phpStudy...
- 计算机中所说的云是什么意思,如何理解云计算中的“云”是什么?
- linux命令行怎么播放,在linux命令行里能听歌看电影吗
- Google Earth Engine(python)——Sentinel 2 影像的地形、坡度、坡向和太阳高度角校正
- R软件--GEO数据分析教程:差异性分析、富集分析(GO\KEGG\DO)
- 2022年全国PMP考试地点汇总,你都知道吗?