程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 一道迅雷筆試題引發的思考?—— 不重復隨機算法

一道迅雷筆試題引發的思考?—— 不重復隨機算法

編輯:C++入門知識

關於一種不重復隨機算法,可以計算0 ~ n中不重復的m個數。

[cpp] 
#include <iostream> 
#include <stdlib.h> 
using namespace std; 
 
void knuth(int n, int m) 

    srand( (unsigned)time( NULL ) ); 
    for( int i = 0; i < n; i++) 
    { 
        if( rand()%(n-i) < m) 
        { 
            cout << i << "\t"; 
            m--; 
        }// end if 
    }//end for 
    return; 

 
int main() 

    knuth(10, 5); 
    return 0; 

常見的算法有2種:

1、用一個大小為n的數組,隨機取出一個,把該位置標為已取,防止下次重復取出;重復m次。缺點是當m接近n時,最後重復取出的概率很大。

2、包0 ~ n放在數組中,通過一些方法打亂順序(比如交換法),然後取出前m個即可。

而上面的方法看起來很神奇,特別是 if ( rand() %(n-i) < m)很讓人不解。帖子的樓主啰嗦了一大堆,於是我干脆自己分析一下。

一、如何不重復

這裡取出發生的代碼是

[cpp] 
cout << i << "\t"; 
 i 在for循環中,每次加1。因此可以保證每次cout都沒有重復。
二、如何保證m次

rand() % (n-i) 的結果是從 [0, n-i]中隨機取出一個,當n-i < m時,則if判斷肯定能成功!m每次判斷成功後都減一,所以這個判斷肯定可以成功m次。而i最小值是0,所以當n > m時,肯定會出現某時刻 n - i < m的情況,所以上面的假設一定成立。


其實上面的算法可以再改一改

[cpp] 
void knuth(int n, int m) 

    srand( (unsigned)time( NULL ) ); 
    for( int i = 0; i < n && m; i++) 
    { 
        if( rand()%(n-i) < m) 
        { 
            cout << i << "\t"; 
            m--; 
        }// end if 
    }//end for 
    return; 

因為當m等於0時,條件二是永遠不能成功的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved