算法相关
洗牌算法
问题描述
如果你想和朋友一起玩扑克游戏,你首先要将牌组随机化,以确保游戏顺利进行。但是怎么做呢? CodeChallenge-day1
solution
这样做的一种简单的方法,是随机的从牌组中拉出一张牌并将其放在一边,重复,逐步建立一个新牌组。只要每次从剩余的牌组中挑选牌的时候,都是相同的概率,就能获得完全无偏的随机牌组:
- 写下从 1 到 N 的数字
- 取一个从 1 到剩下的数字(包括这个数字)的随机数 k
- 从低位开始,得到第 k 个数字(这个数字还没有被取出),把它写在独立的一个列表的最后一位
- 重复第 2 步,直到所有的数字都被取出
- 第 3 步写出的这个序列,现在就是原始数字的随机排列
已经证明如果第 2 步取出的数字是真随机的,那么最后得到的排序一定也是。
这个方案存在一个问题,第三步会浪费太多的时间,如果随机到的K已经被取出了,那就需要跳过,重新取随机数。随着被选出来的牌组越来越多,重复率会越来越大,非常耗费时间。
改进
- 随机生成一个数字k(1到n)
- 交换第k为和第n位元素的值
- n–-
- 如果n == 1,则退出循环,这时候list已经被随机排序了,完成算法
function shuffle(array) {
var m = array.length, t, i;
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}