Метод генерации случайной перестановки, алгоритм Фишера-Йетса
Версия от 20:56, 15 января 2011; Dmitriy D. (обсуждение | вклад)
Содержание
Постановка задачи
Необходимо сгенерировать случайную перестановку из
чисел с равномерным распределением вероятности, если есть в наличии функция для генерации случайного числа в заданном интервале.Решение
Пусть
- random(1..i); генерирует случайное число в интервале
- swap(i, j); меняет местами числа на местах i и j в массиве
- и пусть для определенности массив задан:
Следующий алгоритм решает задачу:
for i = 1..n swap(i, random(1..i))
Этот алгоритм носит имя Фишера-Йетса.
Обоснование
Проведем его по индукции. Требуется доказать, что на каждом шаге цикла каждая перестановка равновероятна.
- при перестановка всего одна, и, очевидно, что база верна
- пусть при каждая перестановка равновероятна, то есть вероятность отдельно взятой перестановки
- после swap(i, random(1..i)) вероятность какого-то числа оказаться на n-ом месте равна , вероятность же какой-то последовательности чисел до n-ого элемента при известном останется , что в результате дает, что вероятность всей перестановки
Другой способ обоснования заключается в том, что каждая перестановка в результате работы этого алгоритма может получиться ровно одним способом, причем всегда ровно за шагов, таким образом автоматически получается, что все перестановок равновероятны.
Неправильные способы реализации
Небольшая модификация этого алгоритма, может резко сказаться на его корректности. Например следующие два алгоритма работают неправильно:
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