2019独角兽企业重金招聘Python工程师标准>>>

原文

记得当年搞NOIp时,我犯过一个相当严重的错误:错误地把Floyd算法的i, j, k三层循环的位置顺序搞颠倒了。直到准备省选时我才突然意识到,Floyd算法应该最先枚举用于松驰操作的那个“中间变量”k,表示只经过从1到k的顶点的最短路;而我却一直习惯性地以为i, j, k应该顺次枚举。令人惊讶的是,这个错误跟了我那么久我居然从来都没有注意到过。后来,我发现有我这种经历的人不止一个。惯性思维很可能会让你接受一些明显错误的算法,并且让你用得坦坦荡荡,一辈子也发觉不了。
    假使你需要把一个数组随机打乱顺序进行重排。你需要保证重排后的结果是概率均等、完全随机的。下面两种算法哪一种是正确的?其中,random(a,b)函数用于返回一个从a到b(包括a和b)的随机整数。

1. for i:=1 to n do swap(a[i], a[random(1,n)]);
2. for i:=1 to n do swap(a[i], a[random(i,n)]);

如果不仔细思考的话,绝大多数人会认为第一个算法才是真正随机的,因为它的操作“更对称”,保证了概率均等。但静下心来仔细思考,你会发现第二种算法才是真正满足随机性的。为了证明这一点,只需要注意到算法的本质是“随机确定a[1]的值,然后递归地对后n-1位进行操作”,用数学归纳法即可轻易说明算法的正确性。而事实上,这段程序一共将会产生n*(n-1)*(n-2)*...*1种等可能的情况,它们正好与1至n的n!种排列一一对应。
     有人会问,那第一种算法为什么就错了呢?看它的样子多么对称美观啊……且慢,我还没说第一种算法是错的哦!虽然第一种算法将产生比第二种算法更多的可能性,会导致一些重复的数列,但完全有可能每种数列重复了相同的次数,概率仍然是均等的。事实上,更有可能发生的是,这两种算法都是正确的,不过相比之下呢第一种算法显得更加对称美观一些。为此,我们需要说明,第一种算法产生的所有情况均等地分成了n!个等价的结果。显然,这个算法将会产生n^n种情况,而我们的排列一共有n!个,因此n^n必须能够被n!整除才行(否则就不能均等地分布了)。但是,n!里含有所有不超过n的质数,而n^n里却只有n的那几个质因子。这表明要想n^n能被n!整除,n的质因子中必须含有所有不超过n的质数。这个结论看上去相当荒唐,反例遍地都是,并且直觉上告诉我们对于所有大于2的n这都是不成立的。为了证明这一点,只需要注意到2是质数,并且根据Bertrand-Chebyshev定理,在n/2和n之间一定还有一个质数。这两个质数的乘积已经大于n了。搞了半天,第一种看似对称而美观的算法居然是错的!

转载于:https://my.oschina.net/darkness/blog/802125

随机洗牌:哪一种算法是正确的?相关推荐

  1. java利用复循环洗牌算法_随机洗牌算法

    今天偶然看到群里的朋友说道,面试被问如何将扑克牌随机洗牌输出.笔者觉得这道题挺有意思而且挺开放性,有多种不同的实现方式.然后我就随手写了一个算法,仔细一想这个算法的优化空间挺大,于是又写出三种算法. ...

  2. 随机洗牌算法之Knuth-Durstenfeld Shuffle

    问题 设计一个公平的洗牌算法 问题分解 首先,必然明确这是一个随机算法 其次,要考虑公平 问题剖析 关于随机 看到随机我们大多数时候想起来的是,把所有的数都放到一个数组里,每次取两个数进行交换,随机 ...

  3. 随机洗牌算法 银行家算法

    1. 随机洗牌算法 https://blog.csdn.net/qq_26399665/article/details/79831490 Fisher-Yates Shuffle算法 最早提出这个洗牌 ...

  4. C#:实现随机洗牌Knuth-Durstenfeld Shuffle算法​(附完整源码)

    C#:实现随机洗牌Knuth-Durstenfeld Shuffle算法 public static void Shuffle<T>(T[] a) {Random rnd = new Ra ...

  5. 随机洗牌算法+matlab,洗牌算法及 random 中 shuffle 方法和 sample 方法浅析

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

  6. shuffle洗牌算法java_js打乱一个数组 的 洗牌(shuffle )算法

    写php的时候 有个shuffle  函数很爽很好用,但是js要实现同样算法的时候发现没有现成函数,在网上看了大量的例子,觉得不靠谱所以,自己写了一个,其实非常简单,以下是实现代码 var shuff ...

  7. 独家 | 决策树VS随机森林——应该使用哪种算法?(附代码链接)

    作者:Abhishek Sharma 翻译:陈超 校对:丁楠雅 本文长度为4600字,建议阅读20分钟 本文以银行贷款数据为案例,对是否批准顾客贷款申请的决策过程进行了算法构建,并对比了决策树与随机森 ...

  8. shuffle洗牌算法java_洗牌算法shuffle

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

  9. 神奇的Knuth洗牌算法

    目录 •写在前面 •一个公平的随机算法? •Knuth算法 •证明思路 •写在前面 谈到随机算法,我们可能脑子里会出现很多种解决方案(ps:想不到解决方案的,可能是random函数用多了,哈哈哈),不 ...

最新文章

  1. es springboot 不设置id_原创 | 一篇解决Springboot 整合 Elasticsearch
  2. Activity管理(一):activity运行机制
  3. python程序实例教程基础-Python程序设计案例教程——从入门到机器学习(微课版)...
  4. Activiti工作流之业务标识和流程的挂起激活
  5. webapi随机调用_BeetleX之webapi验证插件JWT集成
  6. Mybatis JdbcType与Oracle、MySql,javaType数据类型对应列表
  7. 计算机数学基础试题,计算机数学基础(A)综合练习
  8. JQuery LazyLoad实现图片延迟加载-探究
  9. 每天开豪车跟随老板出入高档会所,吃住高档酒店,这样的职场生活,有必要坚持下去吗?
  10. [绝对原创]一些你们想不到的简单方法,就可以让你手机飞快起来!!!
  11. 一种新的排序算法,基于优先队列
  12. Eureka 控制台参数说明
  13. 阿里架构10年,头条开发2年,我终于写出了一套Java核心知识点!
  14. php手机靓号选号系统源码_最好的手机靓号网站源码-鹏博靓号系统
  15. sw转cad映射文件_SolidWorks工程图转CAD图纸DWG文件教程-很吊
  16. Astah 三分钟学会躺着画UML时序图
  17. 我花了一夜用数据结构给女朋友写个H5走迷宫游戏
  18. 国产免费虚拟化OVM与 OpenStack对比
  19. java中英文排序_Java 中英文数字排序
  20. 直播带货这么火,如何在小程序中实现视频通话及直播互动功能?

热门文章

  1. weblogic负载分发
  2. jquery遍历集合数组标签
  3. [20161107]关于数据文件位图区.txt
  4. 使用Action启动/关闭Service
  5. Android清除缓存功能来实现
  6. 引用“.NET研究”类型赋值为null与加速垃圾回收
  7. unbuntu nginx安装详解 /configure: error: the HTTP rewrite module requires the PCRE library
  8. php接受go返回数据,Golang: 接收GET和POST参数(示例代码)
  9. Linux 环境安装 Node、nginx、docker、vsftpd、gitlab
  10. 逆袭之旅DAY17.东软实训.Oracle.存储过程