有一个函数int getNum(),每运行一次可以从一个数组V[N]里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V[N]里随机
2013-12-19 15:03
826 查看
一、题目简介
这个题目出自一道面试题,题目描述如下:
有一个函数int getNum(),每运行一次可以从一个数组V
里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V
里随机取出一个数,而这个数必须是符合1/N平均分布的,也就是说V
里面任意一个数都有1/N的机会被取出,要求空间复杂度为O(1)。
此题思路如下:
设置一个整形nVal,用来存放get()返回的数。调用getNum()从V
取数,按一定概率存入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
二、实现代码
实现代码如下:
[cpp] view
plaincopy
int GetRand()
{
int i=1;
int nRet = 0;
int nVal = 0;
while((nRet=getNum())!=NULL)
{
if(rand()%(i++)==0) nVal = nRet;
}
return nVal;
}
这个题目出自一道面试题,题目描述如下:
有一个函数int getNum(),每运行一次可以从一个数组V
里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V
里随机取出一个数,而这个数必须是符合1/N平均分布的,也就是说V
里面任意一个数都有1/N的机会被取出,要求空间复杂度为O(1)。
此题思路如下:
设置一个整形nVal,用来存放get()返回的数。调用getNum()从V
取数,按一定概率存入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
二、实现代码
实现代码如下:
[cpp] view
plaincopy
int GetRand()
{
int i=1;
int nRet = 0;
int nVal = 0;
while((nRet=getNum())!=NULL)
{
if(rand()%(i++)==0) nVal = nRet;
}
return nVal;
}
相关文章推荐
- 阿里巴巴面试算法题:有一个函数int getNum(),每运行一次可以从一个数组V[N]里面取出一个数,N未知,当数取完的时候,函数返回NULL。现在要求写一个函数int get(),这个函数运行一次可以从V[N]里随机取出一个数,而这个数必须是符合1/N
- 写一个函数int get(),这个函数运行一次可以从V[N]里随机取出一个数,而这个数必须是符合1/N平均分布的
- 一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个rand指针指向这个链表中的一个随机节点或NULL,现在要求复制一个单链表来实现这个链表,返回复制后的新链表。
- 写一个函数,要求传入一个1到n位数的随机数值,如传入随机数123456789,返回12345金币67银币89铜币,传入随机数1234,返回0金币12银币34铜币。 提示:推荐Int,Rnd,Mid,L
- 尝试一个新的函数int_input(),当用户输入整数的时候返回正常,否则提示出错并要求重新输入。
- 编写一个函数,返回一个int数组中存储的最大数值,并在一个简单的程序中测试这个函数。(有缺陷)
- 编写一个函数int_shifts_are_logical(),在对 int 类型的数使用算术右移的机器上运行时,这个函数生成1,而其他情况下生成0
- 【练习】写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)功能:在字符串中找出连续最长的数字串,并把这个串的长度返回,
- 修改magento页面的title,description等------------进而可以写一个descroption数组,让description随机生成-----方便seo,节省在添加产品的时候添加descrition浪费时间
- ios 中调用函数的方法是消息传递,这个和普通的函数调用的区别是,你可以随时对一个对象传递任何消息,而不需要在编译的时候声明这些方法。所以Objective-C可以在runtime的时候
- php-Arrays 函数-array_rand-从数组中随机取出一个或多个单元
- 实现求出若干整数之和为500的连续整数(如98,99,100,101,102)的所有组合&&产生一个int数组,长度为100,并向其中随机插入1~100,要求不能重复
- 百度面试题:有一个很大很大的输入流,大到没有存储器可以将其存储下来,而且只输入一次,如何从 这个输入 流中随机取得 m 个记录。
- 一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它
- 一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。
- 一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。
- 一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它
- 声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,正确的是()
- 从一个数组里面取出一个范围之间的数放倒另一个数组里面
- 一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。 例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3 你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得