相关面试题:
1.n个数中随机取m个 n值非常大
2.连续的网络流中等概率的抽取一个数据包
3.长度为N的链表中(不知道N具体值)一次遍历随机取K个元素
解法:
让我们先来考察第一个问题:n个数中随机选取m个数(此时n值有可能不大)
方法1——等概率抽取法
我们最先想到也是最容易想到的是等概率抽取法,每次都随机在(0,n-1)之间抽取一个数,并与之前的数相比较,若相同,则继续随机生成;若不相同,则继续随机抽取,直到生成一个与之前所有生成数不同的数,将上述这样的随机生成做m次。
那么问题来了,如果m较大呢?
带来的变化是每次调用rand()生成的数与之前的数相重合的概率会变大,换句话说,我要随机取出m个的值,则调用rand()函数的次数会增多,这样的方法开销肯定会增大。
那到底开销有多大呢,我们来考察一下rand()函数的调用次数:
假设前面已经生成了x个数,要生成第x+1个数,那么:
调用1次rand()函数就成功生成该数的概率为: