直接回答:Fisher-Yates:从后往前遍历 i,把 a[i] 与 a[rand(0, i)] 交换,O(n) 时间 O(1) 空间。均匀性直观看:每个位置上的元素是从剩余元素中等概率选出的,全排列共 n! 种,算法的随机选择路径恰好也是 n! 条且一一对应,所以每种排列概率 1/n!。错误写法第一名:sort((a,b) => Math.random()-0.5)——比较器不稳定传递,排序算法的比较序列不可逆推均匀分布,实测某些位置偏好明显。
展开解析:第二类错误:rand(0, n-1) 全程从全部下标选(而非 rand(0, i)),产生 n^n 条路径不能整除 n!,必然不均(n=3 时 27 条路径对 6 种排列,无法等分)。第三类错误:取模偏差——rand() % m 当随机源上限不被 m 整除时低位数概率略高,安全场景用拒绝采样或语言的均匀接口。工程注意:随机源在安全场景(抽奖、密码学洗牌)必须用 CSPRNG;需要可复现(测试、回放)时用种子化 PRNG 并记录种子;分布式场景(多节点各自洗一部分再合并)会破坏均匀性,要么单点洗要么用可证明的分布式协议。验证手段:卡方检验统计各排列频次、或固定元素统计其位置分布。面试延伸:原地随机打乱等价于从排列群均匀采样;与 reservoir sampling 的关系——流式场景 k=n 时两者殊途同归,但洗牌要求全量数据在内存。
追问方向:如何用一个种子实现“确定性洗牌”便于测试?大数组洗牌如何并行化且保持均匀?
(约 460 字)