Перебор перестановок


Перебор всех перестановок

 
В комбинаторике перестановкой называется упорядоченный набор элементов, составленный из элементов исходного множества без повторений


Перестановка, о которой мы здесь поговорим, заключается в том, как расположить n объектов в n позициях. Причем, в перестановке важен порядок элементов.

Как перечислить все перестановки?
Начнем с наименьшего числа (с 1) и далее будем получать все остальные перестановки из оставшихся чисел. Потом возьмем следующее после минимального и опять будем отавлять перестановки из оставшихся чисел по такому же принципу. 
Например, нам необходимо перебрать все перестановки длиной 3 из первых трех букв английского алфавита.  По описанному выше принципу перечисления перестановок, выглядеть список будет таким образом:
ABC
ACB 
BAC 
BCA 
CAB
CBA

Всего перестановк из трех элементов 6.
Для n объектов количество перестановок равно Pn = n!.

Рассмотрим другой полезный подход к решению задачи перебора. Идея заключается в том, чтобы создать глобальный массив, назовем его used, который будет содержать информацию о том, использовали ли мы каждое число или нет. Когда мы рассматриваем очередной элемент для добавления в перестановку, мы проверяем значение в used для этого элемента. Если оно равно false, то это значит, что число ещё не использовалось, и мы можем включить его в перестановку. Затем мы помечаем этот элемент как использованный, устанавливая соответствующий флаг в used на значение true.

Таким образом, мы гарантируем, что каждое число будет использовано только один раз в перестановке, и избегаем повторений.

Запишем алгоритм на псевдокоде

алгоритм generate(n, used, pref)
    если длина(pref) = n то
        check(pref) 
    иначе
        для каждого next от 1 до n выполнить
            если not used[next] то
                used[next] = True
                generate(n, used, pref + [next])
                used[next] = False
            конец если
        конец цикла
    конец если
конец алгоритма

В программе выше используется алгоритм generate, который принимает три параметра: n (максимальное число в перестановке), used (массив, отслеживающий использованные каждого числа) и pref (текущий префикс перестановки).  Если префикс имеет длину n, значит мы добавили в перестановку все числа. Вызываем процедуру check  для обработки перестановки.
Иначе, для каждого числа next от 1 до (включительно), мы проверяем, было ли число использовано ранее (проверка not used[next]). Если число не использовалось, помечаем его как использованное (used[next] = True), рекурсивно вызываем алгоритм generate с обновленными значениями used и pref, и затем освобождаем число для следующей ветки (следующей перестановки), помечая его как неиспользованное (used[next] = False).

Реализуйте данный алгоритм на знакомом вам языке программирования!