Метод генерации случайной перестановки, алгоритм Фишера-Йетса
Версия от 23:13, 15 января 2011; 192.168.0.2 (обсуждение)
Содержание
Постановка задачи
Необходимо сгенерировать случайную перестановку из
чисел с равномерным распределением вероятности, если есть в наличии функция для генерации случайного числа в заданном интервале.Решение
Пусть
- random(1..i); генерирует случайное число в интервале
- swap(i, j); меняет местами числа на местах i и j в массиве
- и пусть для определенности массив задан:
Следующий алгоритм решает задачу:
for i = 1..n swap(i, random(1..i))
Этот алгоритм носит имя Фишера-Йетса.
Обоснование
Проведем доказательство по индукции. Всего перестановок
, поэтому вероятность каждой из них должна быть равна . Показажем, что на каждом i-ом шаге цикла любая перестановка из первых элементов равновероятна.- при перестановка всего одна, и, очевидно, что база верна
- пусть при каждая перестановка первых i элементов равновероятна, то есть вероятность каждой отдельно взятой перестановки на i-ом шаге цикла равна
- при :
- после swap(i, random(1..i)) вероятность какого-то числа оказаться на k-ом месте равна . Вероятность же какой-то перестановки первых (k-1) элементов при известном останется , что в результате дает, что вероятность перестановки первых k элементов равна
Другой способ обоснования заключается в том, что каждая перестановка в результате работы этого алгоритма может получиться ровно одним способом, причем всегда ровно за шагов, таким образом автоматически получается, что все перестановок равновероятны.
Неправильные способы реализации
Небольшая модификация этого алгоритма, может резко сказаться на его корректности. Например, следующие два алгоритма работают неправильно:
for i = 1..n swap(i, random(1..n))
for i = 1..n swap(random(1..n), random(1..n))
В самом деле: число способов сгенерировать последовательность в первом случае равно
, во втором равно , а всего последовательностей . Для того, чтобы сгенерированные последовательности были равновероятны, необходимо хотя бы, чтобы число способов получить последовательность было кратно их общему числу. То есть в первом случае необходимо а во втором случае , что заведомо не выполняется при подстановке любого нечетного числа, начиная с 3.Примечание
- Впервые этот алгоритм опубликовали Р.А.Фишер и Ф.Ятс (R.A.Fisher and F. Yates, Statistical Tables (London 1938), Example 12).
- Нетрудно увидеть, что сложность алгоритма
Литература
- Дональд Кнут Искусство программирования, том 2. Получисленные методы = The Art of Computer Programming, vol.2. Seminumerical Algorithms. — 3-е изд. — М.: «Вильямс», 2007. — С. 832. — ISBN 0-201-89684-2