对这个问题的研究始于一次在群里看到朋友发的洗牌面试题。当时也不知道具体的解法如何,于是随口回了一句:每次从剩下的数字中随机一个。过后找相关资料了解了下,洗牌算法大致有3种,按发明时间先后顺序如下:

一、Fisher–Yates Shuffle

算法思想就是从原始数组中随机抽取一个新的数字到新数组中。算法英文描述如下:

  • Write down the numbers from 1 through N.
  • Pick a random number k between one and the number of unstruck numbers remaining (inclusive).
  • Counting from the low end, strike out the kth number not yet struck out, and write it down elsewhere.
  • Repeat from step 2 until all the numbers have been struck out.
  • The sequence of numbers written down in step 3 is now a random permutation of the original numbers.

python实现代码如下:

#Fisher–Yates Shuffle
'''1. 从还没处理的数组(假如还剩k个)中,随机产生一个[0, k]之间的数字p(假设数组从0开始);2. 从剩下的k个数中把第p个数取出;3. 重复步骤2和3直到数字全部取完;4. 从步骤3取出的数字序列便是一个打乱了的数列。
'''
import randomdef shuffle(lis):result = []while lis:p = random.randrange(0, len(lis))result.append(lis[p])lis.pop(p)return resultr = shuffle([1, 2, 2, 3, 3, 4, 5, 10])
print(r)

二、Knuth-Durstenfeld Shuffle

  Knuth 和Durstenfeld 在Fisher 等人的基础上对算法进行了改进。每次从未处理的数据中随机取出一个数字,然后把该数字放在数组的尾部,即数组尾部存放的是已经处理过的数字。这是一个原地打乱顺序的算法,算法时间复杂度也从Fisher算法的O(n2)提升到了O(n)。算法伪代码如下:

以下两种实现方式的差异仅仅在于遍历的方向而已。下面用python实现前一个:

#Knuth-Durstenfeld Shuffle
def shuffle(lis):for i in range(len(lis) - 1, 0, -1):p = random.randrange(0, i + 1)lis[i], lis[p] = lis[p], lis[i]return lisr = shuffle([1, 2, 2, 3, 3, 4, 5, 10])
print(r)

三、Inside-Out Algorithm

Knuth-Durstenfeld Shuffle 是一个in-place算法,原始数据被直接打乱,有些应用中可能需要保留原始数据,因此需要开辟一个新数组来存储打乱后的序列。Inside-Out Algorithm 算法的基本思想是设一游标i从前向后扫描原始数据的拷贝,在[0, i]之间随机一个下标j,然后用位置j的元素替换掉位置i的数字,再用原始数据位置i的元素替换掉拷贝数据位置j的元素。其作用相当于在拷贝数据中交换i与j位置处的值。伪代码如下:

python代码实现如下:

#Inside-Out Algorithm
def shuffle(lis):result = lis[:]for i in range(1, len(lis)):j = random.randrange(0, i)result[i] = result[j]result[j] = lis[i]return resultr = shuffle([1, 2, 2, 3, 3, 4, 5, 10])
print(r)

四、后话

前面用python实现了三种洗牌算法,其实python random模块也有个shuffle方法,用法如下:

其内部实现正是使用Knuth-Durstenfeld Shuffle算法,不信您看代码:-):

参考:

http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

from: http://www.cnblogs.com/tudas/p/3-shuffle-algorithm.html

洗牌算法shuffle相关推荐

  1. 三种洗牌算法shuffle

    1. 背景 笔试时,遇到一个算法题:差不多是 在n个不同的数中随机取出不重复的m个数.洗牌算法是将原来的数组进行打散,使原数组的某个数在打散后的数组中的每个位置上等概率的出现,刚好可以解决该问题. 2 ...

  2. shuffle洗牌算法java_洗牌算法shuffle

    洗牌算法 1.   背景 阿里的面试的时候做的一道笔试题:题目:写一个方法,入参为自然数n  (n > 0),返回一个自然数数组,数组长度为n,元素为[1,n]之间,且每个元素不重复,数组中各元 ...

  3. JS算法:洗牌算法(shuffle)

    目录 1.洗牌算法 2.JavaScript实现 1.洗牌算法 洗牌(随机)算法有很多应用,例如我们平时用的音乐播放器随机播放,棋牌游戏中的洗牌,扫雷游戏中雷的位置随机等等,都会用到洗牌算法. 思路: ...

  4. 数组洗牌算法-shuffle

    数组洗牌,最近直接的想法是从数组随机取出一个元素,放到另一个数组中,但是这样取出的元素会有重复,必须采取一定的方法保证: 1. 元素不能重复 2. 元素被抽取的概率相等,即随机性 数组洗牌经典算法有两 ...

  5. js(shuffle)洗牌算法

    洗牌算法(shuffle)的js实现 Fisher-Yates 先看最经典的 Fisher-Yates 的洗牌算法 这里有一个该算法的可视化实现 其算法思想就是 从原始数组中随机抽取一个新的元素到新数 ...

  6. 洗牌算法具体指的是什么

    前言: 这里是修真院前端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析前端知识/技能,本篇分享的是: [洗牌算 ...

  7. 等概率随机取数算法的几种实现(洗牌算法)

    等概率随机取数算法的几种实现 最近读了项目中的工具脚本,发现一个随机取数的函数,功能大概是从M个数中不重复的随机取出N个数,算是数组随机排序然后取前N个值的变种. 脚本实现采取原始的方法,每随机取一个 ...

  8. python实现洗牌算法_洗牌算法及 random 中 shuffle 方法和 sample 方法浅析

    对于算法书买了一本又一本却没一本读完超过 10%,Leetcode 刷题从来没坚持超过 3 天的我来说,算法能力真的是渣渣.但是,今天决定写一篇跟算法有关的文章.起因是读了吴师兄的文章 <扫雷与 ...

  9. 从洗牌算法谈起--Python的random.shuffle函数实现原理

    此文首发于我的个人博客:从洗牌算法谈起–random.shuffle实现原理 - zhang0peter的个人博客 昨天看知乎的时候看到了洗牌算法(Knuth shuffle, 最初版本叫Fisher ...

最新文章

  1. 计算机页面的滚动栏怎么拉长,长滚动网页页面设计技巧
  2. Jmeter连接到Mysql
  3. Apache Tomcat/7.0.47
  4. 电子设计竞赛电源题(4)-Buck与Boost电路
  5. 计算机视觉识别简史:从 AlexNet、ResNet 到 Mask RCNN
  6. Android 中的拿来主义(编译,反编译,AXMLPrinter2,smali,baksmali)!
  7. drools 7.x定时器
  8. 《网管员世界2009超值精华本》上市啦!!!
  9. Oracle function注释
  10. 支付宝APP支付里设置应用网关和授权回调地址是不必填的
  11. 【记要】计算机基础通识知识
  12. 教你将视频作为背景添加到另一段视频中
  13. 限时看!阿里、华为数据结构面试必考题!
  14. Photoshop插件-证件照-白红蓝底-PS插件-脚本开发
  15. gis地图php,中国地图矢量gis数据
  16. uniapp苹果无法上架_uniapp无法上架IOS包怎么办
  17. python基础之布尔运算
  18. cad 中的计算机在哪里打开,CAD计算器如何使用?
  19. 3D游戏编程与设计作业六
  20. 那些跳槽做程序员的人,后悔了吗?

热门文章

  1. Spring Cache抽象-缓存注解
  2. 复习(三)—— 进程管理详解
  3. CSDN内容颜色、位置以及图片大小改变
  4. 分布式消息技术 Kafka
  5. springboot打包不同环境配置与shell脚本部署
  6. halcon的算子清点:Chapter 8线的属性
  7. python课堂笔记手抄图片_超简单又漂亮的手抄报图片
  8. js 判断变量是否有值返回bool_有没有办法可以获得javascript函数返回值里的bool值,代码如下:...
  9. Python自然语言处理工具包推荐
  10. 2021-01-07 matlab数值分析 线性方程组的迭代解法 高斯-赛德尔迭代法