算法-洗牌算法

514 阅读2分钟

关键词:数组乱序 Knuth算法 Fisher–Yates shuffle 洗牌算法

洗牌算法是棋牌游戏常用的一种算法,如上面关键词所列举的有好多种不同的叫法。主要解决的问题是: 1.保证数组元素享有同等的排序概率。2.保证排序的效率。

思路:

原始数组是 [1,2,3,4,5,7] , 通过洗牌算法让顺序全部打乱。

注:为了避免连续数字数组的错误理解,这里将第6个元素改成了7。

第一步:如何确定先移动哪一个元素? 随机数做索引就是个不错的办法。

第二步:已排过序的元素就不要动了,让每个元素享有同等的排序权。这就要求索引最大值每次都减1。

第二步:数组排序时要求数组大小不能变,这就要求主动移动元素和目标位置的元素做一个位置交换,这样就可以保证数组大小固定不变。

实现:

有了以上关键思路下面就来实现一下这个洗牌算法。

function shuffle(arr) {
    for (let i=arr.length-1; i>=0; i--) {
        let rIndex = Math.floor(Math.random()*(i+1));
        let temp = arr[rIndex];
        arr[rIndex] = arr[i];
        arr[i] = temp;
    }
    return arr;
}
shuffle([1,2,3,4,5,7]); 
// 结果:1 5 3 7 4 2 

过程分析

这个过程很清晰,只要六次排序,整个数组就完全乱序了,这是随机+二分+交换的综合作用完成的一个排序。

随机数范围(剩余待排元素数量)→ 随机数 → 原始数据(待排) → 结果(已排)
1 2 3 4 5 7
[ 0 , 5 ] 1 1 7 3 4 5 2
[ 0 , 4 ] 3 1 7 3 5 4 2
[ 0 , 3 ] 1 1 5 3 7 4 2
[ 0 , 2 ] 2 1 5 3 7 4 2
[ 0 , 1 ] 1 1 5 3 7 4 2
[ 0 , 0 ] 0 1 5 3 7 4 2

经典的算法很香呀, 即保证公平性又兼顾效率的一个小算法。

拓展:

  • underscore提供了一个shuffle算法
  • 这里有个动画演示洗牌算法的过程

算法在面试中的作用

面试复试我认为分成三大部分内容:1.JS基础知识;2.算法;3.实践经验。

通过实践经验可以综合考察能力,其中就包含算法,而算法一定会包含基础知识点。并且基础知识点一定是通过算法才能真正的掌握,对于工作和面试都是非常重要的。