数组的洗牌算法 | 前端手撕题

2 阅读1分钟

数组的洗牌算法

洗牌算法的新手陷阱

在面试过程当中,尤其是作为前端小白经常会问到“如何实现数组的洗牌算法” 但是如果用以下代码,面试大概率会挂掉

// ❌ 极其危险的错误做法
function badShuffle(arr) {
    return arr.sort(() => Math.random() - 0.5);
}

为什么这个是错误的

Array.prototype.sort() 的底层实现(比如 V8 引擎中的 TimSort)是为了排序设计的

当你把一个随机数硬塞给排序算法时,打破了这种逻辑的传递性。最终的结果是:元素不仅没有被打散,反而有很大的概率留在原来的位置附近。这在数学上完全达不到“等概率”的要求。

正确的洗牌算法

全世界公认的经典算法是 Fisher-Yates 洗牌算法。

伪代码实现:

  1. 从数组末尾开始遍历
  2. 在 [0, i] 的范围内,生成一个随机索引 randomIndex
  3. 交换 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;
}