请用 JavaScript 编写代码,将一个数组的元素顺序随机打乱后输出,要求写出具体实现。
考察说明
考查候选人使用 JavaScript 实现数组随机乱序的能力,重点在于随机算法的正确性与效率。
回答思路
- 【回答框架 1】一种常见方法是使用 Fisher-Yates(也称为 Knuth)洗牌算法。从数组末尾开始,对于每个位置 i,随机生成一个 0 到 i 之间的整数 j,然后交换位置 i 和 j 的元素。这样每个排列出现的概率相等,时间复杂度为 O(n)。
- 【回答框架 2】实现时需要注意使用 Math.random() 生成随机索引,确保随机性均匀。代码示例如下:function shuffle(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } 该代码直接修改原数组并返回。
- 【回答框架 3】另一种常见的错误方法是使用 arr.sort(() => Math.random() - 0.5),这种方法虽然简洁,但随机性不均匀,且排序算法的时间复杂度高于 O(n),不应在正式场景使用。
- 【回答框架 4】如果希望不修改原数组,可以先复制数组再应用洗牌算法。对于大型数组,建议使用 Fisher-Yates 算法以确保性能。
- 【关键点 1】Fisher-Yates 洗牌算法能保证每个排列等概率,时间复杂度 O(n)。
- 【关键点 2】使用 Math.random() 生成随机索引,注意区间为 [0, i] 包含端点。
- 【关键点 3】避免使用 sort 加随机比较函数,因其随机性差且性能不佳。
- 【易错点 1】误以为 sort(() => Math.random() - 0.5) 是合适的乱序方法,会导致分布不均。
- 【易错点 2】忘记将随机索引转换为整数或区间错误,导致范围越界或概率不均。
- 【易错点 3】未考虑是否修改原数组,若需保留原数组应及时复制。