发表于: 2019-04-16 21:02:55

1 646


今天完成的事情:今天讲小课堂,所以没有做多少事情。就看了看洗牌算法

明天计划的事情:用洗牌算法在写一边任务一

洗牌算法,顾名思义,它的产生是用来解决类似洗牌这种场景的问题的,目的是产生一串等概率的随机列,使得很难去预测牌的顺序,洗牌算法是我们常见的随机问题,在玩游戏,随机排序时经常用到。同时它也是一道经典的面试题。

(2)知识剖析:

JavaScript 开发中有时会遇到要将一个数组随机排序(shuffle)的需求,一个常见的写法是这样:

function shuffle(arr) {

arr.sort(function () {

return Math.random() - 0.5;

});

}

 

或者使用更简洁的 ES6 的写法(箭头函数创建更简短的函数和不引入this):

function shuffle(arr) {

arr.sort(() => Math.random() - 0.5);

}

 

(3)常见问题:

但是这种写法有问题,并不能实现真正的随机

这样排序的问题

 

看下面的代码,我们生成一个长度为 10 的数组['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',

'j'],使用上面的方法将数组乱序,执行多次后,会发现每个元素仍然有很大机率在它原来的位置附近出现。

 

let n = 10000;

let count = (new Array(10)).fill(0);

for (let i = 0; i < n; i ++) {

let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];

arr.sort(() => Math.random() - 0.5);

count[arr.indexOf('a')]++;

}

console.log(count);

 

如果排序真的是随机的,那么每个元素在每个位置出现的概率都应该一样,

但是这种排序各个位置的字母会在原位置的左右徘徊。

因此,我们可以认为,使用形如arr.sort(() => Math.random() - 0.5)这样的方法得到的并不是真正的随机排序。

 

浏览器打印台:(10) [2892, 2939, 1968, 1040, 582, 288, 161, 66, 44, 20]

 

国外有人写了一个Shuffle算法可视化的页面,

                    在上面可以更直观地看到使用arr.sort(() => Math.random() - 0.5)的确是很不随机的。

 

 

(4)解决方案:

Fisher–Yates shuffle算法

这个算法由 Ronald Fisher 和 Frank Yates 于 1938 年提出,然后在 1964 年由 Richard Durstenfeld 改编为适用于电脑编程的版本。

遇到的问题:今天因为没有做任务,所以没有什么问题
收获:第一次讲小课堂。让我对BFC加深了印象。感觉以后遇见BFC这一类的问题应该不会出现什么错误。


返回列表 返回列表
评论

    分享到