【算法】Fisher–Yates洗牌算法

for(int i=suit.length-1;i>0;i--)
{
    random1 = Random.next(1,i);
    exchange(suit[random1],suit[i]);
}

为啥是这样呢?

一般会觉得合理的方案如下:

for(int i=0;i<suit.length;i++)
{
    random1 = Random.next(1,n);
    random2 = Random.next(1,n);
    exchange(suit[random1],suit[random2]);
}

这个算法在设计上能够充满整个样本空间,确实存在n!种可能性,但是不够好。

为什么不够好呢,因为这种算法不能够【确保】照顾到每一张牌。

而Fisher–Yates算法在样本空间上,跟前面简单粗暴的随机抽取一样。充满了n!的样本空间,好在哪里呢?

因为它利用了抽卡本身的顺序,【保证照顾】到了每一张原本序列中的卡,而简单粗暴随机抽取存在出现重复位置的可能性,就等于浪费了一次排序的机会,换句话说,其等效抽卡次数因为出现了过去相同的洗法,有效洗牌次数下降,样本空间缩小,无法充满整个n!空间,所以有效性会下降。

而Fisher–Yates算法在原理上保证了不会出现浪费次数,重复选择的情况,导致样本空间一直保持n!,没有坍缩,这就是其在数学意义上优秀的原因。

发布了426 篇原创文章 · 获赞 14 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105489329
今日推荐