一、題目簡介
這個題目出自一道面試題,題目描述如下:
有一個函數int getNum(),每運行一次可以從一個數組V[N]裏面取出一個數,N未知,當數取完的時候,函數返回NULL。現在要求寫一個函數int get(),這個函數運行一次可以從V[N]裏隨機取出一個數,而這個數必須是符合1/N平均分佈的,也就是說V[N]裏面任意一個數都有1/N的機會被取出,要求空間複雜度爲O(1)。
此題思路如下:
設置一個整形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
二、實現代碼
實現代碼如下:
int GetRand()
{
int i=1;
int nRet = 0;
int nVal = 0;
while((nRet=getNum())!=NULL)
{
if(rand()%(i++)==0) nVal = nRet;
}
return nVal;
}