Вы ищете нарушение своих записей.
Прежде всего, ваш алгоритм работает в том смысле, что он выдает случайное расстройство, то есть перестановку без фиксированной точки. Однако у него есть огромный недостаток (на который вы, возможно, не обращаете внимания, но о котором стоит помнить): некоторые нарушения не могут быть получены с помощью вашего алгоритма. Другими словами, это дает нулевую вероятность некоторым возможным расстройствам, поэтому результирующее распределение определенно не является равномерно случайным.
Одним из возможных решений, предложенных в комментариях, было бы использование алгоритма отклонения:
- выбрать перестановку равномерно случайным образом
- если у него нет фиксированных точек, вернуть его
- в противном случае повторите попытку
Асимптотически вероятность расстройства близка к 1/e
= 0,3679 (как видно из статьи в Википедии). Это означает, что для получения беспорядка вам потребуется произвести в среднем e
= 2,718 перестановок, что довольно дорого.
Лучший способ сделать это — отклонять на каждом этапе алгоритма. В псевдокоде примерно так (при условии, что исходный массив содержит i
в позиции i
, т.е. a[i]==i
):
for (i = 1 to n-1) {
do {
j = rand(i, n) // random integer from i to n inclusive
} while a[j] != i // rejection part
swap a[i] a[j]
}
Основное отличие от вашего алгоритма в том, что мы допускаем, что j
равно i
, но только в том случае, если он не дает фиксированной точки. Его выполнение немного дольше (из-за части отклонения) и требует, чтобы вы могли проверить, находится ли запись на своем исходном месте или нет, но у него есть преимущество, заключающееся в том, что он может производить все возможные нарушения (равномерно, для этого иметь значение).
Я предполагаю, что алгоритмы неотклонения должны существовать, но я считаю, что они менее прямолинейны.
Изменить:
Мой алгоритм на самом деле плохой: у вас все еще есть шанс закончить с неперетасованной последней точкой, а распределение вовсе не случайное, см. маргинальные распределения симуляции:
Алгоритм, производящий равномерно распределенные расстройства, можно найти здесь с некоторым контекстом. по проблеме, подробные объяснения и анализ.
Второе редактирование:
На самом деле ваш алгоритм известен как алгоритм Саттоло и Известно, что все циклы производятся с равной вероятностью. Таким образом, любое расстройство, которое не является циклом, а является произведением нескольких непересекающихся циклов, не может быть получено с помощью алгоритма. Например, с четырьмя элементами перестановка, которая меняет местами 1 и 2, 3 и 4, является расстройством, но не циклом.
Если вы не возражаете против получения только циклов, тогда вам подойдет алгоритм Саттоло, на самом деле он намного быстрее, чем любой алгоритм универсального расстройства, поскольку отбраковка не требуется.
person
FelixCQ
schedule
02.09.2011