一、面试题

问:有一个长度为 100 的数组,如何从中随机挑选 50 个元素,组成一个新的数组?

答:这个...那个...emmmmmm

问:那先不挑 50 个,就挑一个数,知道怎么做吗?

答:这个我知道!随机生成一个 0 ~ 99 的数,然后去原数组取对应位置的元素就可以了~

let randomIndex = arr[Math.floor(Math.random() * arr.length)];

问:好,回到最初的问题,怎么挑选 50 个元素?

答:我知道了,在 0 ~ 99 的范围内,随机生成 50 个不重复的数字!

问:是这个思路,具体的实现呢?记得保证效率哦。

答:(吧啦吧啦吧啦)

问:现在假设数组的元素都是 String 类型,如果要把这个数组元素的顺序打乱,有什么办法么?

答:数组的 sort() 方法可以传入一个函数作为参数,这个函数的返回值可以决定排列顺序。在这个函数中写一个随机数,然后就能乱序了。

问:这是一个思路,但这只是伪随机。

答:啊咧?

问:听说过“洗牌算法”吗?

二、随机取数

按照上面随机挑选一个数的思路,从原数组中随机抽取一个数,然后使用 splice 删掉该元素

functiongetRandomArrElement(arr, count) {

let res=[]while (res.length

let randomIdx = (Math.random() * arr.length) >> 0;//splice 返回的是一个数组

res.push(arr.splice(randomIdx, 1)[0]);

}returnres

}

上面生成随机 index 用到了按位右移操作符 >>

当后面的操作数是 0 的时候,该语句的结果就和 Math.floor() 一样,是向下取整

但位操作符是在数值表示的最底层执行操作,因此速度更快

//按位右移

(Math.random() * 100) >> 0

//Math.floor

Math.floor(Math.random() * 100)/*这两种写法的结果是一样的,但位操作的效率更高*/

三、通过 sort 乱序

这个方法可以传入一个参数 compareFunction,这个参数必须是函数

同时 sort() 会暴露出 Array 中的两个元素 (a, b) 作为参数传给 compareFunction

sort() 会根据 compareFunction(a, b) 的返回值,来决定 a 和 b 的相对位置:

如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;

如果 compareFunction(a, b) 大于 0 ,那么 b 会被排列到 a 之前;

如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变(不稳定!)

根据以上规则,可以在 compareFunction 中生成一个随机数,然后根据随机数做运算,返回一个正负未知的 Number,从而实现乱序

functionrandomSort(a,b) {return .5 -Math.random();

}

let arr= ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

arr.sort(randomSort);

但这并不是真正的乱序,计算机的 random 函数因为循环周期的存在,无法生成真正的随机数

四、Fisher–Yates shuffle 洗牌算法

洗牌算法的思路是:

先从数组末尾开始,选取最后一个元素,与数组中随机一个位置的元素交换位置

然后在已经排好的最后一个元素以外的位置中,随机产生一个位置,让该位置元素与倒数第二个元素进行交换

以此类推,打乱整个数组的顺序

functionshuffle(arr) {

let len=arr.length;while(len) {

let i= (Math.random() * len--) >> 0;

// 交换位置

let temp=arr[len];

arr[len]=arr[i];

arr[i]=temp;

}returnarr;

}

再结合 ES6 的解构赋值,使用洗牌算法就更方便了:

Array.prototype.shuffle = function() {

let m= this.length, i;while(m) {

i= (Math.random() * m--) >>> 0;

[this[m], this[i]] = [this[i], this[m]]

}return this;

}

五、用洗牌算法随机取数

再回到从长度为 100 的数组中取 50 个数的问题

之前用的是 splice 修改原数组,如果结合洗牌算法,又会有别的思路

最好是自己先思考一下,然后再展开代码进行比较

functiongetRandomArrElement(arr, count) {

let shuffled= arr.slice(0),

i=arr.length,

min= i -count,

temp,

index;while (i >min) {

index= Math.floor((i--) *Math.random());

temp=shuffled[index];

shuffled[index]=shuffled[i];

shuffled[i]=temp;

}returnshuffled.slice(min);

}

用洗牌算法从数组中随机取数

最后放个彩蛋,关于两种随机取数的性能孰优孰劣

我用 Array.form 生成了一个长度为一百万的数组,然后从中随机取十万个数

首先是使用 splice 的方案:

然后是洗牌算法:

喵喵喵?!!

参考资料:

java 乱序算法_前端面试(算法篇) - 数组乱序相关推荐

  1. fifo算法_前端进阶算法6:一看就懂的队列及配套算法题

    引言 队列这种数据结构,据瓶子君了解,前端需要了解的队列结构主要有:双端队列.滑动窗口,它们都是算法中是比较常用的数据结构. 因此,本节主要内容为: 数据结构:队列(Queue) 双端队列(Deque ...

  2. c++中怎么数组内有用元素的个数_前端面试(算法篇) - 数组乱序

    一.面试题 问:有一个长度为 100 的数组,如何从中随机挑选 50 个元素,组成一个新的数组? 答:这个...那个...emmmmmm 问:那先不挑 50 个,就挑一个数,知道怎么做吗? 答:这个我 ...

  3. @requestparam map 接收前端的值_前端面试总结篇(初级)

    作为一个优秀的程序员,不仅仅可以解决工作的问题,还要不断的关注前端技术的发展,其中也包括了解最新的前端面试题,那么知识点来了,请接好 1. 你熟悉的es6 let.const.var的使用区别 let ...

  4. SLAM算法实习生-实习面试准备篇(1)

    SLAM算法实习生-实习面试准备篇(1) 实习之前投了简历,在简历上介绍了自己掌握的一些知识和技能 这些东西面试是可能问到的,不妨把之前学过的知识认真梳理一下 既然是面试SLAM算法实习生,那就先从& ...

  5. 【Matlab】智能优化算法_蜻蜓优化算法DA

    [Matlab]智能优化算法_蜻蜓优化算法DA 1.背景介绍 2.灵感 3.公式推导 3.1 勘探和开发操作 4.算法流程图 5.文件结构 6.伪代码 7.详细代码及注释 7.1 DA.m 7.2 d ...

  6. 【Matlab】智能优化算法_蚁狮优化算法ALO

    [Matlab]智能优化算法_蚁狮优化算法ALO 1.背景介绍 2.基本思想 3.公式推导 3.1 ALO算法的运算符 3.2 蚂蚁的随机游动 3.3 困在蚂蚁坑里 3.4 修建陷阱 3.5 蚂蚁划向 ...

  7. 【Matlab】智能优化算法_灰狼优化算法GWO

    [Matlab]智能优化算法_灰狼优化算法GWO 1.背景介绍 2.基本思想 2.1 等级制度 2.2 狩猎方式 3.公式推导 3.1 社会等级制度 3.2 包围猎物 3.3 包围猎物 3.4 攻击猎 ...

  8. java 最少使用(lru)置换算法_「面试」LRU了解么?看看LinkedHashMap如何实现LRU算法...

    以下内容均是本人原创,希望你看完之后能有更多更深入的了解,欢迎关注➕ 问题:使用Java完成一个简单的LRU算法 什么是LRU算法 LRU(Least Recently Used),也就是最近最少使用 ...

  9. kruskal算法_大厂面试为什么总是考算法?

    很多同学都问过我这个问题,毕竟,在实际工作中,我们近乎根本不可能从底层实现一遍经典算.法如果真的以工作内容为导向,算法还真可能对绝大部分同学来说没什么用.但是,算法却是大厂面试考察的重点.甚至,极端一 ...

最新文章

  1. 探测电磁波就能揪出恶意软件,网友:搁这给电脑把脉呢?
  2. 2018.4.13 用java配置/生成Xml文件 结合IO流知识点
  3. qt设置文本背景透明_Qt修改图片的背景色及设置背景色为透明的方法
  4. python xlsx 图片_实例11:用Python给Excel所有工作表添加图片
  5. luoguP4755 Beautiful Pair
  6. 计算机系统结构安全检测,信息安全体系结构安全测评实验报告.doc
  7. 放大器的传递函数_这么酷,采用极致小巧的运算放大器设计麦克风电路!
  8. menuStrip1动态添加菜单及快捷键
  9. linux命令中文手册,Linux命令在线中文手册
  10. python转换exe详细教程-手把手教你把Python代码转成exe
  11. 功能强大的全新虚拟商品自动发货商城源码
  12. CentOS7清理磁盘空间
  13. 依存分析:中文依存句法分析简介
  14. 可视化全埋点系列文章之功能介绍篇
  15. Mongodb入门(CRUD与安装)
  16. 0x80070570文件或目录损坏且无法读取解决方法
  17. 【视频学习】李立恒 《阿里铁军销售真经》(完结)
  18. 七夕将至,在线感受程序员男友的浪漫,不要再叫我们直男了好吗!!!
  19. 游戏模型外包-【精刚石数位】
  20. 二叉树之前序遍历、中序遍历、后续遍历

热门文章

  1. 【redis】redis 各种数据类型应用和实现方式
  2. 【ElasticSearch】Es 源码之 NodeClient 源码解读
  3. 【Spring】Spring Access to DialectResolutionInfo cannot be null when ‘hibernate.dialect‘ not set
  4. 【Spark】Spark 2.4 Stream 读取kafka 写入kafka
  5. 【registry】NoSuchFieldError: INCLUDE_ALL
  6. 【Elasticsearch】7.9 单字段支持的最大字符数
  7. 【Java】44个Java代码性能优化总结
  8. 【Kafka】Kafka 配置 SASL_SSL jks鉴权验证方式
  9. 使用 Redis 实现 Session 共享
  10. 【zookeeper】zookeeper的命令行操作zkCli.sh