隨機從長度未知的數組中抽取數字,且保證每個元素被抽到的概率相同

一、題目簡介

    這個題目出自一道面試題,題目描述如下:

   有一個函數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;
}

發佈了61 篇原創文章 · 獲贊 19 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章