发表于: 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这一类的问题应该不会出现什么错误。
评论