洗牌算法及其证明

问题定义:

给定有序序列1-n,要求将其打乱,使得每个元素在任意位置出现的概率均为1/n。

程序实现:

void shuffle(int *arr, int n)      // n为序列中元素总数
{
    int idx;
    for(int i = 0; i < n; i++)
    {
        idx = rand() % (i+1);      // idx在下标[0, i]内
        swap(&arr[idx], &arr[i]);
    }
}

数学归纳法证明:

(1)当n=1时,idx必为0,所以元素arr[0]在任何一个位置的概率为1/1,命题成立。

(2)假设当n=k时,命题成立,即n=k时,原数组中任何一个元素在任何一个位置的概率为1/k。

 

(3)则当n=k+1时,由以上假设知,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k;

  当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); 

  在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1);

  故前k个元素在任意位置的的概率都为1/(k+1);

  所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。

    对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-1/(k+1)) * (1/k) = 1/(k+1),所以对于第k+1个元

  素,其在整个数组前k+1个位置上的概率也均为1/k+1。

 

(4)综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。

原文地址:https://www.cnblogs.com/1203ljh/p/4734514.html