今天看到了网易往年的一题面试题,是要写洗牌算法及其证明的。要保证每张牌的概率都是1/N。
假设有N张牌。用数组poker[]表示。
srand(time(NULL));
for(int i = 0; i < N; ++i) {
int temp = rand() % (i+1);
if(temp != i)//这里有i/(i+1)的概率交换,而每张牌被交换的概率为1/i
swap(poker[i],poker[temp]);
}
下面为证明过程:
就像上面所说的那样。
没个循环,都保证了牌的概率为1/(i+1);
证明如下:
首先,temp是0~i,概率为1/(i+1),所以temp != i的概率为i/(i+1)
其次,temp之前一共有i个数,每个数的概率都是相等的(这里其实可以用数学归纳法),那么每个数被交换的概率是,1/i * i/(i+1) = 1/(i+1)
得证。