shuffle洗牌算法java_洗牌算法shuffle[通俗易懂]

洗牌算法1.背景阿里的面试的时候做的一道笔试题:题目:写一个方法,入参为自然数n(n>0),返回一个自然数数组,数组长度为n,元素为[1,n]之间,且每个元素不重复,数组中各元素顺序要求随机;实例1:输入:N=3输出:132实例2:输入:N=5输出:32514当时我的解法(写了两种方法):写的好烂,面完和面试官交流的时候面试官让我看下Collect…

大家好,又见面了,我是你们的朋友全栈君。

5f86bc314e29

洗牌算法

1.   背景

阿里的面试的时候做的一道笔试题:题目:写一个方法,入参为自然数n  (n > 0),返回一个自然数数组,数组长度为n,元素为[1,n]之间,且每个元素不重复,数组中各元素顺序要求随机;

实例1: 输入: N = 3  输出: 132

实例2: 输入: N = 5   输出: 32514

当时我的解法(写了两种方法):

5f86bc314e29

5f86bc314e29

写的好烂,面完和面试官交流的时候面试官让我看下Collections.shuffle的源码,于是乎就开始研究这个“洗牌算法”。

2.洗牌算法

洗牌就是将原有的排序打乱的一个过程,我们可以通过抽牌、换牌和插牌三种方式进行洗牌。最常用的洗牌算法:即Fisher-Yates Shuffle和Knuth-Durstenfeld Shhuffle,我们分别学习一下两种洗牌算法。

2.1 Fisher-Yates Shuffle

所述费舍尔-耶茨洗牌是一种算法:用于产生随机排列的有限的序列,简单地说,该算法对序列进行洗牌。

算法的自然语言描述为(给定1到N的序列):①记下从1到N的数字。

②从1到结尾的未删除数字(包括)之间选择一个随机数k。

③从低端开始计数,剔除尚未剔除的第k个数字,并将其写下一个单独的列表的末尾。

④从第2步开始重复,直到所有数字都被删除。

⑤现在在步骤3中写下的数字序列就是原始序列的随机排列。

理论上的费舍尔-耶茨洗牌算法的时间复杂度为O(n²),空间复杂度O(n)。

2.2 Knuth-Durstenfeld Shuffle

所述克努斯-杜斯腾菲尔德算法是一个现代版的费舍尔-耶茨算法,我们实现Fisher和Yates算法时会花费不必要的时间来用来计算上面第3步中的剩余数字,但Durstenfeld的解决方案是将“删除”的数字移到列表的末尾,然后将每个被删除的数字交换为最后一个未删除的数字迭代,简言之:每次迭代时交换这个被取出的数字到原始列表的最后。这将算法的时间复杂度从O(n²)降低到了O(n)。

伪代码实现://To shuffle an arrayaofnelements  (indices  0…n-1):

forifromn−1down to1do

j← random integer such that 0 ≤j≤iexchangea[j] anda[i]

按照上述的伪代码的描述,我们使用JS实现这段伪代码:

5f86bc314e29

使用ES6实现的

Knuth-Durstenfeld Shuffle

算法需要的时间正比于要随机置乱的数,不需要额为的存储空间开销,时间复杂度为O(n),空间复杂度O(1)。

3.

Collections.shuffle()

源码解析:

5f86bc314e29

shuffle方法的入口

传入待洗牌的List集合,定义一个随机数种子。

5f86bc314e29

shuffle的具体实现

获取集合的长度,其中SHUFFLE_THRESHOLD = 5,当list的长度<5或者list实现了RandomAccess接口的时候,通过倒序的循环交换索引位置与随机生成的[0,i)的索引位置。

当集合长度>5的时候,将集合转为数组,然后再次进行随机值交换,然后将数组重新set到集合里面去,这样做避免了将“顺序访问”列表洗牌到适当的位置而导致的二次行为。

主意事项:

1)用List list=ArrayList(Arrays.asList(ia)),用shuffle()打乱不会改变底层数组的顺序。

2)用List list=Arrays.aslist(ia),然后用shuffle()打乱会改变底层数组的顺序。

可以使用洗牌算法实现扫雷。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126128.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 旅游吧

    旅游吧生活在城市里的人,都习惯了朝九晚五的生活……每天思想被缩进在身体里,把所有的不如意压抑下去,即使可以大发雷霆,但还是要循规蹈矩的奔上那开往公司的公车……每个跳跃的灵魂被催眠了,换而代之的则是慢慢下垂的累眼……每人都在自己的座位上,无数次的敲打着键盘,习惯了这个习惯的动作,习惯了这个习惯的声音,习惯了这个习惯的频率……在这个北京的大都市,北漂随处可见,想想那在农村,从村头喊一声传到村

    2022年6月12日
    58
  • DOM笔记2

    DOM笔记2

    2022年1月7日
    57
  • idea2021.8.2激活码(JetBrains全家桶)

    (idea2021.8.2激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~BCEBXQ3A4G-eyJsaWNlbnNlSWQiOi…

    2022年3月22日
    48
  • connect A with B_anyconnect怎么用

    connect A with B_anyconnect怎么用解决git下载出现:Failedtoconnectto127.0.0.1port1080:Connectionrefused拒绝连接错误(20190226)文章目录:一、git拒绝连接原因分析二、错误解决方式1、查看Linux当前有没有使用代理2、查看端口有没有被占用2、取消代理设置linux解决端口号被占用(扩展内容)不知道是不是翻墙导致的错误,昨天同事说服务器出现了这个错误……

    2022年9月7日
    0
  • 黑客初学者刷屏技巧_初学者,这些技巧将加速您的编码

    黑客初学者刷屏技巧_初学者,这些技巧将加速您的编码黑客初学者刷屏技巧Whenyoujuststartoutyourprogrammingjourney,therearesomanyshinytoolsandtechnologiestoexplore,youalmostdon’tknowwheretostart.Fortunately,therearenumerousguidesonho…

    2022年5月2日
    49
  • SQL中的long text

    SQL中的long textSQL中的longtext问题:解决方法:SELECTCONVERT(VARCHAR(5000),参考文献)AS参考文献FROMtpi20160503出现原因:转载于:https://www.cnblogs.com/Renyi-Fan/p/7792499.html…

    2022年5月14日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号