前言
本篇文章记录下我在笔试过程中遇到的真实题目,供大家参考。
1、题目
系统给定一个数组,需要我们编写一个函数,该函数每次调用,随机从该数组中获取一个数,且不能与上一次的取数相同。
2、思路解析
数组已经有了,我们首先想到的就是通过使用 Math.random()
方法来获取一个随机数,而且这个随机数的范围要在数组的长度范围内,这样才能根据数组的下标获取到对应的数组的值。
我们知道,Math.random()
方法是获取 0 ~ 1
之间的随机数,包含 0 但不包含 1
如何才能获取到 0 ~ 数组长度-1 区间范围内的随机数呢?而且还需要是整数。
显然,此时我们已经有了获取 0 ~ 1 之间的随机数,当这个随机数 乘以 数组长度的时候,我们就可以获取一个 0 ~ 数组长度之间的随机数。
下一个方向是:保证每次获取的随机数都是整数
Math还提供了另外三个方法:Math.floor()
、 Math.ceil()
、Math.round()
- Math.floor():向下取整,即小数部分直接舍弃。
- Math.ceil():向上取整,即舍弃小数部分,同时整数部分 + 1
- Math.round():四舍五入,返回四舍五入后的整数
针对于我们应该使用哪个方法:我们可以思考下:
Math.random()
方法产生的随机数,包含0,却不包含1,这意味着,当我们再乘以数组长度的时候,得到的树,永远也不会包含数组长度的值。即:如果数组长度为 5 ,我们得到的随机数永远也不会为 5。
显而易见,此时使用 Math.floor()
方法向下取整,我们获取的随机整数,永远都会是数组的下标。
重点:如何让本次取到的数,和上次不同
这里面有两个不同的地方:
1. 当数组中的元素都是不同元素时
2. 当数组中有相同元素时
所以需要数组去重,校验下,必须保证数组中起码有三个不同的数字。
思路:定义一个变量:存放上次取的随机数,每次调用该方法时,进行对比,如果相等,则代表和上次取数一样,此时再次调用该函数(递归),如果不等,则返回。
3. 代码实例
const data = [1,2,3,4,5,6,1,2]
let lastNum = null; // 用于存放上次的取数
const getRandomNum = (arr) => {
if(!arr.length) return; // 封装方法时的习惯性写法,可不写
let newArr = (data) => [...new Set(data)] // 去重
if(newArr(arr).length < 3) return; // 确保数组的不同元素超过三个
let random = Math.floor(Math.random() * arr.length) // 获取 0~数组长度-1 的随机数
if(lastNum == arr[random]) {
return getRandomNum(arr)
}
lastNum = arr[random]
return arr[random]
}
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
console.log(getRandomNum(data))
效果如下所示: