工作中经常会用到洗牌算法,看到这篇文章不错,原文摘自:http://www.atatech.org/article/detail/11821/928  作者:子仲
 
场景
洗牌算法的应用场景其实很多,运营的坑位固定,需要随机显示是一种场景。用音乐播放的时候,随机播放列表,其实主要用的就是shuffle算法。谁都不希望随机一两次之后又听到同一首歌。IPod shuffle的卖点其实就在这。我们平时在人数固定的情况下就会用到shuffle算法。总得来说洗牌算法场景较多,下面我们来看看它的实现原理。
 
实现
洗牌算法是实现方式
第一种我叫它正常洗牌抽牌法
桌上有n张扑克牌,第i次从桌子上等概率随机取出一张扑克牌,此时牌堆的减少一张,在n-i的牌堆里面再随机等概率抽取一张,直到抽完为止。
deck 为扑克牌 
1    for i <-  0 to  n
2 d<-random(n-i)
3 swap(deck[d],deck[n-i])
还有一种方式就是标记法,就是抽牌的人从牌堆里面随机抽出一张牌,然后标记为已读,然后放回牌堆里面,继续随机抽取,如果遇到“已读‘标记的,就放回。直到抽到无已读为止。这种方式和前面的方式实现简直就是高富帅和屌丝之间的差别。因为这种方式就是你要随机到所有的牌都出现过为止。一句话“远离此方法,争做有爱青年“
 
javascript实现
 
 
第一种实现:
1    function shuffle0(array) {
2 array.sort(function() {
3 return Math.random() - 0.5;
4 });
5 return array;
6 }

这是一种不完全的洗牌算法

 
第二种实现:
1    function shuffle1(array) {
2 for (var i = array.length - 1; i > 0; i--) {
3 var j = Math.floor(Math.random() * (i + 1));
4 var temp = array[i];
5 array[i] = array[j];
6 array[j] = temp;
7 }
8 return array;
9 }

这是理想的算法

 
第三种实现:
01    function shuffle2(array) {
02 var copy = [], n = array.length, i;
03
04 while (n) {
05 i = Math.floor(Math.random() * array.length);
06
07 if (i in array) {
08 copy.push(array[i]);
09 delete array[i];
10 n--;
11 }
12 }
13
14 return copy;
15 }

这就是前面说到的屌丝算法

 
第四种实现:
1    function shuffle3(array) {
2 var copy = [], n = array.length, i;
3 while (n) {
4 i = Math.floor(Math.random() * n--);
5 copy.push(array.splice(i, 1)[0]);
6 }
7
8 return copy;
9 }
 
看来像O(n) 但是由于splice的缘故,这个算法也有可能出现O(n^2)的情况
demo
多做一步
谁才是中国好随机?才是真随机?
接下来让我们重复30遍来看看效果
我们来制定一个判断标准:随机之后出现在自己的位置的数量越少说明随机的越彻底,反之则说明越不彻底
1    var sum = 0;
2 for(var i=0;i<30;i++) {
3 var a = [0,1,2,3,4,5,6,7,8,9];
4 console.log(shuffleN(a));
5 for(var j=0;j<10; j++) {
6 if(a[j]==j) sum++;
7 }
8 }
9 console.log('随机重复数:'+sum)

第一种

第二种
第三种
第四种
性能对比
我们来对四种方法做下性能对比: http://jsperf.com/sm-shuffle
通过对比
第二种方法的效率最高
第三种效率最差
 
总结
选择一种算法实现,时间复杂度、空间复杂要考虑,对于像这种随机算法,我觉得还需要一个准确度。
第一种方法由于不能做到真正意义上的随机,所以可以不考虑。
第二种效率最高,但是也会出现重复,但是可以接受,因为更接近现实中的随机情况
第三种效率最差,而且是全随机,效率差到爆,那就不多说了
第四种如果做全随机的话,我觉得可以选用这种方式,也会出现效率问题。
 

闲话shuffle(洗牌)算法的更多相关文章

  1. random array & shuffle 洗牌算法 / 随机算法

    random array & shuffle shuffle 洗牌算法 / 随机算法 https://en.wikipedia.org/wiki/Fisher–Yates_shuffle ES ...

  2. Fisher–Yates shuffle 洗牌算法(zz)

    1,缘起 最近工作上遇到一个问题,即将一组数据,比如[A,B,C,D,E]其中的两个B,E按随机排列,其他的仍在原来的位置: 原始数组:[A,B,C,D,E] 随机字母:[B,D] 可能结果:[A,B ...

  3. Fisher–Yates shuffle 洗牌算法

    Fisher-Yates shuffle 是一种生成有限序列的随机排列的算法--简单地说,该算法可以对序列进行混排.本人能力有限,且懒.不会扒论文去研究该算法在数学上的证明,只能抄袭网上的博客总结一遍 ...

  4. 洗牌算法shuffle

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

  5. 洗牌算法及 random 中 shuffle 方法和 sample 方法浅析

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

  6. 随机洗牌算法Knuth Shuffle和错排公式

    Knuth随机洗牌算法:譬如现在有54张牌,如何洗牌才能保证随机性.可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止.参考代码 ...

  7. js 随机数 洗牌算法

    function shuffle(arr){ var len = arr.length; for(var i = 0;i<len -1;i++) { var idx = Math.floor(M ...

  8. 519. Random Flip Matrix(Fisher-Yates洗牌算法)

    1. 问题 给定一个全零矩阵的行和列,实现flip函数随机把一个0变成1并返回索引,实现rest函数将所有数归零. 2. 思路 拒绝采样 (1)先计算矩阵的元素个数(行乘以列),记作n,那么[0, n ...

  9. 《Algorithms算法》笔记:元素排序(3)——洗牌算法

    <Algorithms算法>笔记:元素排序(3)——洗牌算法 Algorithms算法笔记元素排序3洗牌算法 洗牌算法 排序洗牌 Knuth洗牌 Knuth洗牌代码 洗牌算法 洗牌的思想很 ...

  10. Python洗牌算法重写

    Python有自带的洗牌算法函数shuffle(). 自己也通过学习也琢磨了一下它的实现,然后给出一个时间复杂度O(n),空间复杂度O(4)的例子: import random def shuffle ...

随机推荐

  1. zoj 1033 与其说是搜索,不如说是枚举

    zoj 与其说是搜索,不如说是枚举,只不过是通过搜索来实现的罢了. 主要是要注意好闰年的判断,特别是要注意好一串数字的划分. 题意其实我也看了一个晚上,才渐渐的看懂. 题意: 给你一个字符串,其中包含 ...

  2. Windows中APACHE开启fastcgi后无法连接数据库

    环境:Windows server 2003 x64Apache 2.2.14mod_fcgid-2.2b-w32.zipPHP VC9 x86 Non Thread Safe(用Visual C++ ...

  3. (转)如何在Excel2013中制作条形码

    文章来源:http://www.officezhushou.com/excel2013/3905.html 注意:如果发现条形码不能移动的情况,请点击开发工具-设计模式,那么你就可以移动你的条形码了 ...

  4. WordPress模版结构

    一套完整的WordPress模版应至少包括如下文件: style.css : 样式表文件 index.php : 首页模板 archive.php : 文章归档/分类目录模板 404.php : 40 ...

  5. linux中grep和egrep的用法

    1. grep简介 grep (global search regular expression_r(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大 ...

  6. Storm系列(十七)DRPC介绍

    Storm版本0.9.5 在storm中DRPC服务应用于远程分布式计算,根据客户端提交的请求参数,而返回Storm计算的结果. DRPC服务启动流程(远程模式) 启动DRPC服务,启动命令:stor ...

  7. 【Java基础】用LinkedList实现一个简单栈的功能

    栈的基本功能 栈的最基本功能是保障后进先出,然后在此基础上可以对在栈中的对象进行弹入弹出,此外,在弹出时,如果栈为空,则会报错,所以还需要提供获取当前栈大小的方法. 构造存储对象Student /** ...

  8. HDOJ-ACM1021(JAVA)

    题意: 斐波拉契数列的另外一个变型,如果F(n)能被3整除,则输出yes,否则输出no.(n<1000000) 解题思路: 看到(n<1000000)这个条件,有点感觉递归量有点大,因此要 ...

  9. Tuple元组

    Tuple元组 Tuple 是 Storm 的主要数据结构,并且是 Storm 中使用的最基本单元.数据模型和元组. Tuple 描述 Tuple 就是一个值列表, Tuple 中的值可以是任何类型的 ...

  10. mac下apache启动关闭操作

    1.一般的命令如下: 2.但是这种方法在mac上有的时候不生效 3.根据上面的提示使用下面的方法,可以生效,mac上很多应用都可以采用这种方式启动.关闭应用 sudo launchctl load / ...