Посмотрите на код. Имеет 2 вложенных цикла:
- Внешний цикл перебирает позиции
val
.
- Внутренний цикл находит индекс значения, который должен быть в индексе
val
, т.е. max_pos
.
Требуется много времени, чтобы найти индекс. Вместо этого я вычислю индекс каждого значения и сохраню его в dict
.
index_of = {value: index for index, value in enumerate(arr)}
(обратите внимание, что поскольку все значения в arr
различны, дублирующихся ключей быть не должно)
А также подготовьте отсортированную версию массива: таким образом легче найти максимальное значение, вместо того, чтобы циклически перемещаться по массиву.
sorted_arr = sorted(arr)
Затем сделайте все остальное, как в исходном коде: для каждого посещенного индекса используйте sorted_arr
, чтобы получить максимум, или index_of
, чтобы получить его текущий индекс, если он неуместен, то поменяйте местами. Не забудьте обновить index_of
dict при замене тоже.
Алгоритм принимает O(n)
операций (включая dict
индексирование / изменение), плюс стоимость сортировки n
элементов (что составляет около O(n log n)
).
Примечание. Если массив arr
содержит только целые числа в небольшом диапазоне, может быть быстрее сделать массив index_of
вместо dict
.