僞隨機解決真隨機問題

1.從文件中隨機取一行數據

如果先統計文件有多少行,再根據rand() % 行數選擇對應行也是可以行的,但效率顯然會有點低了。有沒有一種方法可以只遍歷文件一次了?請看代碼:

  1. //從文件中取機選取一行  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <time.h> 
  5. #include<fstream> 
  6. int main()  
  7. {  
  8.     printf("           從文件中取機選取一行 \n");  
  9.   
  10.     int i, num, nChooseNum;  
  11.     const char strFileName[] = "in.txt";  
  12.       
  13.     fd=ifstream(strFileName);  
  14.     srand(time(NULL));  
  15.     i = 1;  
  16.     string line;
  17.     while (getline(fd,line))  
  18.     {  
  19.         if (rand() % i == 0)  
  20.             nChooseNum = num;  
  21.         i++;  
  22.     }  
  23.     printf("從文件中選取出: %d\n", nChooseNum);  
  24.     return 0;  
  25. }  

假設有三行,

(1)i==1,if()爲真的概率爲 1

 (2)1==2,if()爲真的概率爲 1/2

  (3) i==3,if()爲真的概率爲1/3

所以選擇一行的概率,(1)爲真,(2),(3)爲假概率爲1*  1/2  *  2/3   =1/3。選擇第一行的概率爲1/3

其他行同理均是1/n 的概率。


2.谷歌筆試題:如何隨機選取1000個關鍵字

給定一個數據流,其中包含無窮盡的搜索關鍵字(比如,人們在谷歌搜索時不斷輸入的關鍵字)。如何才能從這個無窮盡的流中隨機的選取1000個關鍵字?

定義長度爲1000的數組。

對於數據流中的前1000個關鍵字,顯然都要放到數組中。

對於數據流中的的第n(n>1000)個關鍵字,我們知道這個關鍵字被隨機選中的概率爲 1000/n。所以我們以 1000/n 的概率用這個關鍵字去替換數組中的隨機一個。這樣就可以保證所有關鍵字都以 1000/n的概率被選中。

對於後面的關鍵字都進行這樣的處理,這樣我們就可以保證數組中總是保存着1000個隨機關鍵字。


代碼

需要考慮的問題
1.n<m,需要釋放申請的空間
2.m<0; 
3.n>=m; 使用完空間後,需要釋放空間

int* getRandomMLine(unsigned int m)
{
	int *nChoosen=new int[m];
		unsigned int lineNum=0;
	srand((unsigned int )time(0));
	char c;
	while((c=getchar())!='\n') //模擬去讀一行
	{
		lineNum++;
		if(lineNum<=m)
		{
			nChoosen[lineNum-1]=lineNum;  //把前M行,拷貝到蓄水池中;
		}
		else if(rand()%lineNum<m)// 以M/N的概率選擇一行
		{
			int location=rand()%m;
			nChoosen[location]=lineNum;
		}

	}
	if(lineNum<m)
	{
		delete[] nChoosen;
		return NULL;
	}
	else
	return nChoosen;
}


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