三种经典的洗牌算法

  • Post author:
  • Post category:其他



参考原文链接:

https://blog.csdn.net/qq_25026989/article/details/89512769


问题描述:


洗牌算法是将原来的数组进行打散,使原数组的某个数在打散后的数组中的每个位置上等概率的出现。


主要有3中经典的洗牌算法:


1.

抽牌


1.初始化原始数组和新数组,原始数组长度为n(已知);

2.从还没处理的数组(假如还剩k个)中,随机产生一个[0, k)之间的数字p(假设数组从0开始);

3.从剩下的k个数中把第p个数取出;

4.重复步骤2和3直到数字全部取完;

5.从步骤3取出的数字序列便是一个打乱了的数列。


时间复杂度为O(n*n),空间复杂度为O(n).


2.

换牌




原地打乱顺序


):

1. 建立一个数组大小为 n 的数组 arr,分别存放 1 到 n 的数值;

2. 生成一个从 0 到 n – 1 的随机数 x;

3. 输出 arr 下标为 x 的数值,即为第一个随机数;

4. 将 arr 的尾元素和下标为 x 的元素互换;

5. 同2,生成一个从 0 到 n – 2 的随机数 x;

6. 输出 arr 下标为 x 的数值,为第二个随机数;

7. 将 arr 的倒数第二个元素和下标为 x 的元素互换;

……

如上,直到输出 m 个数为止




时间复杂度为O(n),空间复杂度为O(1)


缺点必须知道数组长度n.原始数组被修改了,这是一个原地打乱顺序的算法,算法时间复杂度也从Fisher算法的 O(n2)提              升到了O(n)。由于是从后往前扫描,无法处理不知道长度或动态增长的数组。


3.

插牌

(蓄水池抽样):

1.先选中第1到k个元素,作为被选中的元素。然后依次对第k+1至第N个元素做如下操作:

2.每个元素都有k/x的概率被选中,然后等概率的(1/k)替换掉被选中的元素。其中x是元素的序号。

从N个元素中随机等概率取出k个元素(洗牌发牌可以认为k=1),N长度未知。

在o(n)时间内对n个数据进行等概率随机            抽取

。如果数据集合的量特别大或者还在增长(相当于未知数据集合总量),该算法依然可以等概率抽样.



版权声明:本文为xfwdxt原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。