1. 編寫一個方法,洗一副牌。要求作到完美洗牌,換言之,這副牌52!中排列組合出現的機率相同。假設給定一個完美的隨機數發生器。html
假設有個方法shuffle對n-1個元素有效,咱們能夠用它來打亂n個元素的次序。咱們會先打亂前n-1個元素的次序,而後,取第n個元素,將它與數組中的元素隨機交換。這是遞歸的思想。算法
這裏咱們使用的迭代方法,咱們要作的就是遍歷整個數組,對每一個元素i,將array[i]與0和i(含)之間的隨機元素交換。數組
//隨機數產生器 int random(int lower, int higher) { return lower + (rand() % (higher - lower + 1)); } //遞歸 void shuffleArrayRecursively(int cards[], int i) { if(i == 0) return; shuffleArrayRecursively(cards, i - 1); //打亂先前部分的次數 int k = random(0, i); //隨機挑選索引進行交換 swap(cards[k], cards[i]); } //迭代 void shuffleArrayInteratively(int cards[], int n) { for(int i = 0; i < n; i++) { int k = random(0, i); swap(cards[k],cards[i]); } }
2. 編寫一個方法,從大小爲n的數組中隨機選出m個整數。要求每一個元素被選中的機率相同。dom
關於這個問題的證實解釋能夠參見機率問題spa
這種問題和隨機洗牌算法類似,因此我放在一塊兒說。咱們能夠先取出源數組中的前m個元素,而後從元素m開始,迭代訪問原數組,只要k<m,就將array[i]插入到目的數組中(隨機選出)位置k。code
//隨機數產生器 int random(int lower, int higher) { return lower + (rand() % (higher - lower + 1)); } void pickMIteratively(int original[], int data[], int n, int m) { for(int i = 0; i < m; i++) { data[i] = original[i]; } for(int i = m; i < n; i++) { int k = random(0, i); if(k < m) data[k] = original[i]; } }