一、面试题

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

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

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

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

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

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

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

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

答:(吧啦吧啦吧啦)

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

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

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

答:啊咧?

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

二、随机取数

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

function getRandomArrElement(arr, count) { let res = [] while (res.length < count) { // 生成随机 index let randomIdx = (Math.random() * arr.length) >> 0; // splice 返回的是一个数组 res.push(arr.splice(randomIdx, 1)[0]); } return res}

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

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

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

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

三、通过 sort 乱序

首先认识一下 Array.prototype.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,从而实现乱序

function randomSort(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 洗牌算法

洗牌算法的思路是:

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

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

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

function shuffle(arr) { let len = arr.length; while (len) { let i = (Math.random() * len--) >> 0; // 交换位置 let temp = arr[len]; arr[len] = arr[i]; arr[i] = temp; } return arr;}

再结合 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 修改原数组,如果结合洗牌算法,又会有别的思路

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

function getRandomArrElement(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; } return shuffled.slice(min);}

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

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

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

首先是使用 splice 的方案:

然后是洗牌算法:

希望对你有用。

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

  1. java 乱序算法_前端面试(算法篇) - 数组乱序

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

  2. vue 判断同一数组内的值是否一直_前端代码+后端API,值得一学的Vue高仿音乐播放器实战项目

    项目名称:vue-fds_music 项目作者:符道胜 开源许可协议:Apache-2.0 项目地址:https://gitee.com/fudaosheng/vue-fds_music 项目简介 V ...

  3. 【Java方法】统计数组内不同元素个数及每个元素的数量

    [Java方法]统计数组内元素的种类数及每种元素的数量 1.统计数组内元素的种类数 2.统计数组内每种元素的数量 我们假定一个一维数组 a={1,2,3,2,2,3,1,3,2,1,2,3,1,2,1 ...

  4. python简单小案例列表_python计算列表内各元素的个数实例

    python计算列表内各元素的个数实例 如下所示: list = [1,2,3,4,5,6,7,5,4,3,2,12] set = set(list) dict = {} for item in se ...

  5. java array 元素的位置_数据结构与算法:动态图解十大经典排序算法(含JAVA代码实现)...

    点击上方"JAVA",星标公众号 重磅干货,第一时间送达 本文将采取动态图+文字描述+正确的java代码实现来讲解以下十大排序算法: 冒泡排序 选择排序 插入排序 希尔排序 归并排 ...

  6. c语言 数组比较不等往下累加,用C语言确定两个数组内的元素排列顺序不同,但是元素相同,代码有bug找不出?...

    我觉得稍微麻烦一点的就是允许数组内有重复,我想了两个办法,一种是排序好再挨个比较.另外一个我写了出了,但是跑不正确,怎么弄k都等于10,代码如下,请看出bug的大神指点: int thr_bg(int ...

  7. 怎么区分html外联内联,HTML中什么是内联元素?

    在HTML中,内联元素是指display属性为inline的元素:内联元素也叫行内元素,在网页中总是随着文字流出现在"行内",这些元素不会在它本身之前或之后生成"分隔符& ...

  8. html 内联元素转换,HTML中什么是内联元素?

    在HTML中,内联元素是指display属性为inline的元素:内联元素也叫行内元素,在网页中总是随着文字流出现在"行内",这些元素不会在它本身之前或之后生成"分隔符& ...

  9. css的内联是什么,css中什么是内联元素

    css中的内联元素也称为行内元素:内联元素包括布局中常用的标签如a.span.em.b.strong.i等:内联元素和它的兄弟元素之间一个挨着一个,并且都在同一行按从左至右的顺序显示,不单独占一行. ...

最新文章

  1. 我的MYSQL学习心得(十六) 优化
  2. Zabbix JVM 安装
  3. Spring Boot国际化支持
  4. linux进程池 自动增长,linux下C 线程池的原理讲解和代码实现(能自行伸缩扩展线程数)...
  5. k8s核心技术-命令行工具kubectl---K8S_Google工作笔记0017
  6. 提升SQL Server速度 整理索引碎片
  7. 计算机等级二级c语言考试真题,历年计算机等级考试二级C语言上机真题及答案..pdf...
  8. 解决开发工具文件夹拖不进图片文件
  9. unity商店demo学习:俯视视角RPG游戏
  10. LA 3713 Astronauts
  11. 算法来为图像找到好的裁剪
  12. 现有存储系统技术架构
  13. 理财笔记 - 给朋友的建议
  14. Spring Boot电商项目46:购物车模块四:【添加商品到购物车】接口;(如果:接口要求返回JSON格式,而接口没有做相应的设置,是会报404错误的)
  15. Linux入门级操作实例--vi和vim编辑器的使用
  16. OpenMP编程(4)—sections、single指令
  17. 2021年汽车驾驶员(初级)考试APP及汽车驾驶员(初级)考试软件
  18. 【分享】一年级古诗古朗月行语文知识点心田花开汇总
  19. pymol作图-氢键
  20. 图像去雾(image dehazing)近期论文简述及模型测试

热门文章

  1. javascript学习系列(3):数组中的foreach方法
  2. 前端学习(3100):vue+element今日头条管理-react简介
  3. 实现深拷贝的几种方法
  4. 前端学习(2944):前一天回顾
  5. [jQuery] jQuery与jQuery UI有啥区别?
  6. 工作374-前端margin:0 auto为什么会失效
  7. [css] 如何使用CSS3的属性设置模拟边框跟border效果一样?
  8. 工作293:新的打印操作
  9. 前端学习(220):伪元素选择器
  10. 第三十六期:学 Java 网络爬虫,需要哪些基础知识?