前段時間面試碰到一道題,題目主要就是隨機打亂一個數組的順序。乍一聽我以爲挺簡單的,可是到寫代碼的時候卻有種「無從下手」的感受,緣由在於本身其實以前並無使用過(也沒有仔細思考過)「隨機性」。javascript
Math.random()
返回一個隨機數,均勻分佈在[0,1)
範圍。用這個方法咱們能夠在任意範圍產生隨機數。
好比java
Math.random()*10
:均勻分佈在[0,10)
範圍的有理數。Math.floor(Math.random()*10)
:均勻分佈在[0,9]
範圍的整數(獲得0~9這10個整數的機率相同)。Math.floor(Math.random()*10)+55
:均勻分佈在[55,64]
範圍的整數(獲得這10個整數的機率相同)。更通常化的,產生指定範圍的隨機有理數方法:面試
// 產生一個[min,max)範圍的隨機有理數 function getRandomArbitrary(min, max) { return Math.random() * (max - min) + min; }
產生指定範圍的隨機整數的方法:算法
// 產生一個[min,max]範圍的隨機整數,注意這個範圍包含max function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
上面這個方法中的+ 1
是一個很容易遺漏的地方,考慮一下爲何Math.floor(Math.random()*10)
最大隻能產生9。數組
一個簡潔的辦法是,利用sort:dom
function shuffle(array) { array.sort(function() { return 0.5 - Math.random(); }); }
可是這種方法並不能作到真正的「均勻打亂」,能夠看看參考資料3中的知乎討論。
這位答主結合生動的圖片解釋了更好的均勻打亂算法:Fisher–Yates shuffle。code
function shuffle(array) { var m = array.length, t, i; while (m) { i = Math.floor(Math.random() * m--); t = array[m]; array[m] = array[i]; array[i] = t; } return array; }
這裏就不盜人家的圖了,讀者能夠點擊連接查看。
這個簡潔的算法不難理解,主要的步驟是i = Math.floor(Math.random() * m--)
,這個語句先獲取一個[0,m-1]
範圍的隨機下標賦值給i
,而後m=m-1
。圖片