一道来自 前端工作越来越难找,是不是已经饱和了? 中的面试题:

编写一个 JavaScript 函数 fn,该函数有一个参数 n(数字类型),其返回值是一个数组,该数组内是 n 个随机且不重复的整数,且整数取值范围是 [2, 32]。

解法一

思路:

  1. 填充一个 2 到 32 的有序数组 A
  2. 填充一个长度为 n 的空数组 B
  3. 随机从 A 里面删除 n 个元素,然后一直把删掉的元素替换掉 B 的元素
1
2
3
4
5
6
7
function fn(n) {
const data = []
for (let i = 2; i < 33; i++) data.push(i)
return new Array(n)
.fill()
.map(() => data.splice(Math.floor(Math.random() * data.length), 1)[0])
}

解法二

思路:

  1. 填充一个 2 到 32 的有序数组
  2. 打乱该数组
  3. 取该打乱数组的前 n 个元素
1
2
3
4
5
function fn(n) {
const data = [] // 这个data还可以考虑缓存起来 下次就不需要填充了
for (let i = 2; i < 33; i++) data.push(i)
return data.sort(() => 0.5 - Math.random()).slice(0, n)
}

瑕疵是上面的数组打乱是伪随机算法,不过一定程度上能够满足本题的需求。最佳的打乱算法可以参考 Fisher-Yates

总结

以上两种解法的好处都是通过在不重复元素中随机取元素来规避去重步骤


 评论