Простой алгоритм: составить все перестановки, отсортировать, выбрать предыдущее число, меньшее текущего, работает долго. Если число состоит из N цифр, то количество перестановок N!. Сложность сортировки такого массива равна O(N!×log N!).
Нужен более быстрый алгоритм, корректность которого надо проверить.
Во-первых, попробуем разобраться, когда у нас вообще возможен результат. Что значит, что у нас не может быть числа, меньше исходного?
Посмотрим на примеры: 1234, 357, 689. 1 < 2 < 3 < 4, 3 < 5 < 7, 6 < 8 < 9.
Если цифры числа упорядочены от меньшей к большей, то мы имеем наименьшее число.
Посмотрим на число 1243, для которого наименьшим будет 1234. Если мы будем идти от младшей цифры (это 3) к старшей (это 1) и сравнивать две соседние цифры, то обнаружим, что 4 > 3. Нам останется поменять 4 и 3 местами, чтобы получить результат.
Всегда ли достаточно одной перестановки?
Рассмотрим число dd...dd978
, где d
— какие-то десятичные цифры. Это такое большое число, которое заканчивается на 978. Поменям местами 9 и 8, получим число dd...dd879
. Это следующее число, меньшее, чем dd...dd978
?
Нет. Следующее число dd...dd897
и чтобы его получить, нужны две перестановки. Это значит, что ни один простой алгоритм с одной перестановкой не даст нам гарантированного результата.
Рассматривая последний результат, мы понимаем, что речь идёт не о произвольной перестановке. По сути, цифры после 8 упорядочиваются в порядке убывания, тогда мы получаем следующее наименьшее число.
Чтобы проиллюстрировать идею, рассмотрим число 236145. Рассматриваем его с конца. Вторая с конца цицфа 4, 4 < 5, всё нормально. Следующая цифра 1, 1 < 5, всё нормально. Далее 6, 6 > 5. Мы нашли позицию, ниже которой можем найти меньшее число.
Переставляем на место 6 самую большую из цифр справа, то есть 5. Остальные цифры упорядочиваем в порядке убывания. Получаем 235641.
Поскольку нам нужно упорядочивать массив, значения которых принимают всего десять значений от '0' до '9', мы можем использовать счётную сортировку. Мы будем получать результат за O(N), где N — длина числа.
Реализацию писать не буду — в Питоне не силён. Но алгоритм, кажется, верный.