隨機生成1~n的某一排列,要求生成每種可能的排列的概率相同 。
算法描述:
給定數值分別為1~n的序列a,
循環變量i從1到n,每次循環將a[i]
與a[i]~a[n]
中的隨機某元素交換,最后a數組即為隨機生成的某一排列。
#include <iostream>
#include <ctime>
using namespace std;
#define N 100005
int a[N];
int randInt(int a, int b)
{return rand()*rand()%(b-a+1)+a;
}
int main()
{srand(time(NULL));int n;cin >> n;for(int i = 1; i <= n; ++i)a[i] = i;for(int i = 1; i <= n; ++i){int j = randInt(i, n);swap(a[i], a[j]);}for(int i = 1; i <= n; ++i)cout << a[i] << ' ';return 0;
}
原序列a,每個元素的值分別為 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1?,a2?,...,an?
證明:依照以上方法生成的每種排列的概率相同
探究生成排列 a x 1 a x 2 . . . a x n a_{x1}a_{x2}...a_{xn} ax1?ax2?...axn?的概率
對于第1個數 a x 1 a_{x1} ax1?。第1次交換,在第1~n個數中選擇 a x 1 a_{x1} ax1?的概率為 1 n \frac{1}{n} n1?,將 a 1 a_1 a1?與 a x 1 a_{x1} ax1?交換。
對于第2個數 a x 2 a_{x2} ax2?。第2次交換,在第2~n個數中選擇 a x 2 a_{x2} ax2?的概率為 1 n ? 1 \frac{1}{n-1} n?11?
…
對于第n個數 a x n a_{xn} axn?。第n次交換,在第n~n個數中選擇 a x n a_{xn} axn?的概率為 1 1 1
根據乘法原理,生成排列 a x 1 a x 2 . . . a x n a_{x1}a_{x2}...a_{xn} ax1?ax2?...axn?的概率為 1 n ? 1 n ? 1 ? . . . ? 1 = 1 n ! \frac{1}{n}*\frac{1}{n-1}*...*1=\frac{1}{n!} n1??n?11??...?1=n!1?
對于任意給定的排列,按照上述算法得到該排列的概率都是 1 n ! \frac{1}{n!} n!1?,命題得證。