数组的洗牌算法
洗牌算法的新手陷阱
在面试过程当中,尤其是作为前端小白经常会问到“如何实现数组的洗牌算法” 但是如果用以下代码,面试大概率会挂掉
// ❌ 极其危险的错误做法
function badShuffle(arr) {
return arr.sort(() => Math.random() - 0.5);
}
为什么这个是错误的
Array.prototype.sort() 的底层实现(比如 V8 引擎中的 TimSort)是为了排序设计的
当你把一个随机数硬塞给排序算法时,打破了这种逻辑的传递性。最终的结果是:元素不仅没有被打散,反而有很大的概率留在原来的位置附近。这在数学上完全达不到“等概率”的要求。
正确的洗牌算法
全世界公认的经典算法是 Fisher-Yates 洗牌算法。
伪代码实现:
- 从数组末尾开始遍历
- 在 [0, i] 的范围内,生成一个随机索引 randomIndex
- 交换 i 和 randomIndex 的元素
function shuffle(arr) {
// 倒序遍历数组
for (let i = arr.length - 1; i >= 0; i--) {
// 生成随机缩影
const randomIndex = math.floor(math.random() * (i + 1));
// 交换 i 和 randomIndex 的元素
[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
}
return arr;
}