随机生成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}
ax1ax2...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}
ax1ax2...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,命题得证。