Fisher–Yates shuffle 算法 – To Be Hacker-演道网
2016 年 12 月 2 日
导言
Fisher–Yates shuffle 是一个将序列打乱的“洗牌”算法。由 Ronald Fisher 与 Frank Yates 在 《Statistical tables for biological, agricultural and medical research》一书中最先提出,因此得名。
其后 Donald Knuth 在《The Art of Computer Programming》一书中将其推广开来,故又称之为 Knuth shuffle 。
算法思想
Fisher and Yates 最初的方法
FISHER 与 YATES 最初提出这个算法时,计算机尚没有普及,所以说这是一种在纸笔上操作的算法。除此之外,你还需要一个随机数表用以提供随机性。
算法的执行过程如下:
- 将序列写成一行,并赋予下标 1 到 N
- 生成一个 1 到现有序列长度之间的随机数 K
- 从左往右,将序列中第 K 个数拿出来追加到一个新的序列中
- 重复2、3步,直至所有的数都已被拿入新序列
- 这个新序列即为一组原序列的随机排列
当今的算法
Fisher与 Yates 最初的算法适合纸笔操作,但对计算机而言并不友好。为此 Richard Durstenfeld 在 1964 年针对于计算机对其作出了一些改进:
- 将序列 lst 标上下标,从 0 到 n-1
- 设一变量 i 等于 n-1
- 生成一个 0 到 i 的随机数 r ,将 lst[r] 与 lst[i] 交换
- i 自减 1
- 重复 2-4 步,直至 i 等于 0
- 序列 lst 即为一组原序列的随机排列
(这里 i 是从 n-1 到 0 的。类似的,i 从 0 到 n-1 也是可以的,这里就不再累述了。)
算法改变的并不多,但影响却是巨大的。他将一个时间复杂度为 O(n^2) 的算法优化为了一个 O(n) 的算法。其关键在于原算法的第三步消耗了很多无用的计算在数数上。
示例
Wikipedia 上有两份详细的示例,点击这里。
实现
了解算法思想后实现非常简单,下面是一份 Python 3 的实现:
参考:
Wikipedia:本篇 Post 的主要素材,上面的解释非常详细
转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn