洗牌算法

背景:

洗牌对于棋牌游戏是必不可少的一个过程;

再有一类问题可以用洗牌算范完美解决:随机生成不重复的N以内的数

shuffle(洗牌)

查了有限的几个博客,洗牌算法按照出现的时间顺序总共有三种

1,Fisher–Yates Shuffle

该洗牌算法的主要思想是:

1,从原始序列的k个数里面随机取一个数m(randome(0,k)),

2,把m放入到输出序列中,

3,把原始序列从m到k依次往前移动,使原始序列剩余k-1个数;

4,重复1-3步骤,直到剩余0个数。

时间复杂度O(n2)   空间复杂度O(n)

 

 

2.Knuth-Durstenfeld Shuffle 

该洗牌算法主要思想是:

首先继承了FY洗牌算法的思想,再在此算法基础上做了改进。具体表现为:

1,从原始序列的k个数里面随机取一个数m(randome(0,k)),

2,交换原始序列第m个数和第k个数的值,swap(array[m],array[k]),认为第k个数是已经处理过的数字

3,不再对原始序列第k个数进行任何操作,原始序列变为k-1个数,

4,重复1-3步骤,原始序列变为k-1个数。知道k=1为止。

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

 

3,Inside-Out Algorithm

KD洗牌算法的优点是:时间复杂度和空间复杂度都比较好,KD洗牌算法是in-place的排序方法。

如果有这样一个特殊需求(什么应用场景,我也没用想到,只是隐隐感觉应该有这个需求):需要查看原始的未排序的数据。

那么KD洗牌算法就满足不了了,这个时候就需要应用Inside-Out Algorithm。

该算法的主要思想是:

1,首先拷贝一份原始序列。

2,从头到尾遍历拷贝序列,假设当前游标i,则生成[0,i]之间的随机数j,把原始序列的array[j]赋值给array[i];把拷贝序列的copy_array[i]赋值给原始序列的array[j],其实就是swap(array[i],array[j])。只是利用了拷贝序列,少了一次交换操作而已。

总结下:

跟KD算法的区别在于:

1,保留了原始序列,代价是多了一次原始序列的拷贝,以做他用。

2,KD算法取随机数的范围是从K开始越来越小;IO算法取随机数的范围是从1开始到K,越来越大。

3,KD算法是交换当前序列最大下标的值和生成的随机数对应的序列值;IO算法也是交换当前遍历序列的最大值和生成的随机数对应的序列值,后者利用了拷贝序列,所以交换次数少了1.

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值