工作中经常会用到洗牌算法,看到这篇文章不错,原文摘自: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. 关于“javax.servlet.include.request_uri”属性值

    在springMVC的DispatcherServlet类的doService方法中有如下代码: if (WebUtils.isIncludeRequest(request)) { attribute ...

  2. DedeCms 5.7友情链接模块注入漏洞

    漏洞版本: DedeCms 5.7 漏洞描述: DedeCms基于PHP+MySQL的技术开发,是目前国内应用最广泛的php类CMS系统. DedeCms 5.7前台提交友情链接处,可以插入恶意JS代 ...

  3. lightoj 1003

    有向图拓扑排序,判段是否存在. #include<map> #include<cstdio> #include<string> #include<cstrin ...

  4. 自动化测试实施的几个idea

    UI检查.测试的一个idea 在电子商务网站中, 为达到较好的用户体验, 可能页面上会有大量的UI设计,一堆css.ajax效果等,敏捷开发中, UI变动更是带来了测试的苦恼.对于回归组catch U ...

  5. 安装protobuf及相关的lua生成器

    1.google code 需要用到的水星:http://mercurial.selenic.com/ 2.protobuf地址 https://code.google.com/p/protobuf/ ...

  6. Windows下部署Git Server端

    解决方案一: (注意:如果英文阅读没太大障碍,直接到Bonobo官网看相关文档即可.) win7(windows server 2008应该也可以,没测试过)+ IIS7.5(win7自带的)+ Gi ...

  7. 排列的学习(java)

    1.无重复排列 2.有重复排列 3,下一个排列 package 生成排列; public class Main { static int count=0; //a中保存原来的排列,lev表示选定第几个 ...

  8. tmux快捷键`

    Ctrl+b 激活控制台:此时以下按键生效 系统操作 ? 列出所有快捷键:按q返回 d 脱离当前会话:这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话 D 选择要脱离的 ...

  9. 《Introduction to Algorithm》-chaper33-计算几何学

    叉积: 在平面中我们为了度量一条直线的倾斜状态,为引入倾斜角这个概念.而通过在直角坐标系中建立tan α = k,我们实现了将几何关系和代数关系的衔接,这其实也是用计算机解决几何问题的一个核心,计算机 ...

  10. jpcap 配置方法,问题解决,模拟sniffer程序。(附JAVA程序,jar,dll包等环境)

    博文链接 http://www.cnblogs.com/xckk/p/4609444.html 一.   Eclipse环境下安装与配置Jpcap 相关源程序.jpcap jar包,dll包,帮助文档 ...