費雪耶茨洗牌
也被稱為 Knuth shuffle 和 Durstenfeld-Fisher-Yates shuffle。這個 shuffle 採用了一系列 n
元素並將其洗牌。該演算法是真正隨機的,因為在混洗之後,陣列的每個排列都是同樣可能的。
在 java 中:
public static void shuffle(E[] deck) {
//From the end, swap each card with a random card from the unswapped portion.
for(int i = deck.length - 1; i > 0; i--)
{
//Pick an element from [0,i], inclusive.
int chosenCard = (int) (Math.random() * (i + 1));
E temp = deck[i];
deck[i] = deck[chosenCard];
deck[chosenCard] = temp;
}
}
請注意:替換元素必須來自[0,i]包含而不是[0,i]獨佔:否則,元素保留到位的陣列的排列是不可能的,這不是真正隨機的。
假設假設隨機數採用 O(1)
生成,則演算法就地執行並佔用 O(n)
時間和空間。以這種方式混洗的陣列可用於檢索每個元素的 O(1)
攤銷時間中的非重複元素。
E[] deck;
int drawIndex;
//Elements are taken from an index that advances.
public E drawUniqueCard()
{
//Once all cards have been drawn, reshuffle the deck and draw from the top.
if(drawIndex == deck.length)
{
shuffle(deck);
drawIndex = 0;
}
//Pull the next card off the deck.
return deck[drawIndex++];
}