fisher-yates shuffle洗牌算法

当需要随机打乱一个数组的顺序,你可能想要学习这个算法。具体的历史参见维基百科

这里简单翻译一下维基的介绍

fisher-yates是一种算法,用来在有限的序列中产生一个随机的排列,通俗一点说就是给定一个数组,这个算法可以随机打乱它的顺序。这个算法的命名是取自Ronald Fisher和Frank Yates。

下面是js版本, 复杂度是O(N):

function shuffle(array) {
  var m = array.length, t, i;
  while (m) {
    i = Math.floor(Math.random() * m--);
    console.log(m)
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }

  return array;
}

我们来说明一下这个函数的执行步骤:比如有一个数组 arr = [‘a’,’b’,’c’,’d’,’e’], 调用shuffle(arr):

shuffle(['a','b','c','d','e'])
随机数i的值 0 m的值为 4 数组值为 (5) ["e", "b", "c", "d", "a"]
随机数i的值 0 m的值为 3 数组值为 (5) ["d", "b", "c", "e", "a"]
随机数i的值 0 m的值为 2 数组值为 (5) ["c", "b", "d", "e", "a"]
随机数i的值 1 m的值为 1 数组值为 (5) ["c", "b", "d", "e", "a"]
随机数i的值 0 m的值为 0 数组值为 (5) ["c", "b", "d", "e", "a"]

注意这里 m 的值, 每次把数组前部任意一个位置和数组最后一个值交换位置。 这里的数组指的是每次交换完不包括最后一个值的数组。可能描述的不清楚,请看上面执行的例子。

python自带随机数组函数

from random import shuffle, sample

list = [1,2,3,4,5,6]

shuffle(list)  #将改变原list数组
sample(list, k=len(list))   #生成新的数组