Есть ли эффективный алгоритм (эффективный с точки зрения большой записи O), чтобы найти число свопов для преобразования перестановки P в подстановку I? Сделки не обязательно должны находиться на соседних элементах, но на любых элементах.
Итак, например:
I = {0, 1, 2, 3, 4, 5}, number of swaps is 0
P = {0, 1, 5, 3, 4, 2}, number of swaps is 1 (2 and 5)
P = {4, 1, 3, 5, 0, 2}, number of swaps is 3 (2 with 5, 3 with 5, 4 with 0)
Одна идея - написать такой алгоритм:
int count = 0;
for(int i = 0; i < n; ++ i) {
for(; P[i] != i; ++ count) { // could be permuted multiple times
std::swap(P[P[i]], P[i]);
// look where the number at hand should be
}
}
Но мне не совсем понятно, действительно ли это завершено или найдет правильное количество свопов. Он работает над приведенными выше примерами. Я попытался создать все перестановки на 5 и на 12 номеров, и он всегда заканчивается на них.
Эта проблема возникает в числовой линейной алгебре. В некоторых матричных разложениях используется поворот, который эффективно свопит строку с наибольшим значением для следующей строки, которой нужно манипулировать, чтобы избежать деления на небольшие числа и улучшить численную стабильность. Некоторые декомпозиции, такие как декомпозиция LU, могут впоследствии использоваться для вычисления матричного определителя, но знак детерминанта декомпозиции противоположен признаку исходной матрицы, если число перестановок нечетное.
EDIT. Я согласен, что этот вопрос похож на Подсчет смежных свопов, необходимых для преобразования одной перестановки в другую. Но я бы сказал, что этот вопрос более фундаментален. Преобразование перестановки из одного в другое можно преобразовать в эту проблему, инвертируя целевую перестановку в O (n), составив перестановки в O (n), а затем найдя количество свопов оттуда к идентификатору. Решение этого вопроса путем явного представления тождества как другой перестановки кажется субоптимальным. Кроме того, у другого вопроса до вчерашнего дня было четыре ответа, в которых только один (по | \/| ad) был, по-видимому, полезен, но описание метода казалось неопределенным. Теперь пользователь lizusek предоставил ответ на мой вопрос. Я не согласен с тем, что этот вопрос повторяется как дубликат.
EDIT2. Предлагаемый алгоритм фактически представляется довольно оптимальным, как указано в комментарии пользователя rcgldr, см. мой ответ на Подсчет смежных свопов требуется для преобразования одной перестановки в другую.