Как вы генерируете все перестановки списка в Python, независимо от типа элементов в этом списке?
Например:
permutations([])
[]
permutations([1])
[1]
permutations([1, 2])
[1, 2]
[2, 1]
permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
python
algorithm
permutation
combinatorics
python-2.5
Рикардо Рейес
источник
источник
Ответы:
Начиная с Python 2.6 (и если вы на Python 3) у вас есть стандартная библиотека инструмент для этого:
itertools.permutations
.Если по какой-то причине вы используете старый Python (<2.6) или вам просто интересно узнать, как он работает, вот один хороший подход, взятый из http://code.activestate.com/recipes/252178/ :
Несколько альтернативных подходов перечислены в документации
itertools.permutations
. Вот один из них:И еще один, основанный на
itertools.product
:источник
for i in range(len(elements))
вместоfor i in range(len(elements)+1)
. Фактически выделенный элементelements[0:1]
может находиться вlen(elements)
разных положениях, в результате чего нетlen(elements)+1
.И в Python 2.6 и далее:
(возвращается как генератор. Используйте,
list(permutations(l))
чтобы вернуться как список.)источник
r
параметр, напримерitertools.permutations([1,2,3], r=2)
, который будет генерировать все возможные перестановки, выбирая 2 элемента:[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
Следующий код с Python 2.6 и выше ТОЛЬКО
Во-первых, импорт
itertools
:Перестановка (порядок имеет значение):
Комбинация (порядок не имеет значения):
Декартово произведение (с несколькими итерациями):
Декартово произведение (с одной итерацией и само собой):
источник
называется как:
источник
Вывод:
Поскольку я меняю содержимое списка, в качестве входных данных требуется изменяемый тип последовательности. Например,
perm(list("ball"))
будет работать иperm("ball")
не будет, потому что вы не можете изменить строку.Эта реализация Python основана на алгоритме, представленном в книге « Компьютерные алгоритмы» Горовица, Сахни и Раджасекерана .
источник
Это решение реализует генератор, чтобы избежать хранения всех перестановок в памяти:
источник
В функциональном стиле
Результат:
источник
Следующий код представляет собой перестановку на месте данного списка, реализованную в виде генератора. Поскольку он возвращает только ссылки на список, список не должен изменяться вне генератора. Решение нерекурсивное, поэтому использует мало памяти. Хорошо работают также с несколькими копиями элементов в списке ввода.
источник
Совершенно очевидным способом на мой взгляд может быть также:
источник
Вывод:
источник
Я использовал алгоритм, основанный на системе факторных чисел. Для списка длины n вы можете собрать каждый элемент перестановки по элементам, выбирая из элементов, оставленных на каждом этапе. У вас есть n вариантов для первого элемента, n-1 для второго и только один для последнего, так что вы можете использовать цифры числа в системе факторных чисел в качестве индексов. Таким образом, числа от 0 до n! -1 соответствуют всем возможным перестановкам в лексикографическом порядке.
вывод:
Этот метод не рекурсивный, но он немного медленнее на моем компьютере, и xrange вызывает ошибку, когда n! слишком велик, чтобы его можно было преобразовать в длинное целое число C (для меня n = 13). Этого было достаточно, когда мне это было нужно, но это далеко не itertools.permutations длинным выстрелом.
источник
Обратите внимание, что этот алгоритм имеет
n factorial
временную сложность, гдеn
длина списка вводаРаспечатать результаты на бегу:
Пример:
Вывод:
источник
Можно действительно перебрать первый элемент каждой перестановки, как в ответе Цвенна. Однако более эффективно написать это решение следующим образом:
Это решение примерно на 30% быстрее, по-видимому, благодаря рекурсии, заканчивающейся
len(elements) <= 1
вместо0
. Это также намного более эффективно использует память, поскольку использует функцию генератора (сквознуюyield
), как в решении Риккардо Рейеса.источник
Это вдохновлено реализацией Haskell, использующей понимание списка:
источник
Обычная реализация (без выхода - все сделает в памяти):
Выход реализации:
Основная идея состоит в том, чтобы пройти все элементы в массиве для 1-й позиции, а затем во 2-й позиции пройти через все остальные элементы без выбранного элемента для 1-й и т. Д. Это можно сделать с помощью рекурсии , где критерием остановки является получение массива из 1 элемента - в этом случае вы возвращаете этот массив.
источник
perms = getPermutations(array[:i] + array[i+1:])
numpy
массив _>getPermutations(np.array([1, 2, 3]))
, я вижу, что он работает для списка, просто запутался, как аргумент funcarray
:)numba
и стал жадным со скоростью, поэтому пытался использовать его исключительно сnumpy
массивамиДля производительности, решение Numpy, вдохновленное Кнутом , (стр. 22):
Копирование больших блоков памяти экономит время - это в 20 раз быстрее, чем
list(itertools.permutations(range(n))
:источник
источник
Вот алгоритм, который работает со списком без создания новых промежуточных списков, аналогично решению Бер на https://stackoverflow.com/a/108651/184528 .
Вы можете попробовать код для себя здесь: http://repl.it/J9v
источник
Красота рекурсии:
источник
Этот алгоритм является наиболее эффективным, он избегает передачи массивов и манипуляций при рекурсивных вызовах, работает в Python 2, 3:
Применение:
источник
источник
ДРУГОЙ ПОДХОД (без библиотек)
Ввод может быть строкой или списком
источник
[1, 2, 3]
возвращается[6, 6, 6, 6, 6, 6]
print(permutation(['1','2','3']))
Отказ от ответственности: бесформенный плагин от автора пакета. :)
Пакет trotter отличается от большинства реализаций тем, что он генерирует псевдо-списки, которые на самом деле не содержат перестановок, а скорее описывают сопоставления между перестановками и соответствующими позициями в упорядочении, что позволяет работать с очень большими «списками» перестановок, как показано в этой демонстрации, которая выполняет довольно мгновенные операции и поиск в псевдосписке, «содержащем» все перестановки букв в алфавите, без использования большего количества памяти или обработки, чем обычная веб-страница.
В любом случае, чтобы сформировать список перестановок, мы можем сделать следующее.
Вывод:
источник
Генерация всех возможных перестановок
Я использую python3.4:
Тестовые случаи:
источник
Чтобы сэкономить много часов на поиске и экспериментировании, вот решение для нерекурсивных перестановок в Python, которое также работает с Numba (начиная с версии 0.41):
Чтобы произвести впечатление о производительности:
Так что используйте эту версию, только если вам нужно вызывать ее из функции njoted, в противном случае предпочтите реализацию itertools.
источник
Я вижу много итераций внутри этих рекурсивных функций, не совсем чистых рекурсия ...
так что для тех из вас, кто не может соблюдать даже один цикл, вот грубое, совершенно ненужное полностью рекурсивное решение
источник
Другое решение:
источник
Мое решение Python:
источник
Вывод: ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
источник
С помощью
Counter
источник