Digamos que tengo una lista de n elementos, ¡sé que hay n! posibles formas de ordenar estos elementos. ¿Qué es un algoritmo para generar todos los posibles ordenamientos de esta lista? Por ejemplo, tengo la lista [a, b, c]. El algoritmo devolvería [[a, b, c], [a, c, b,], [b, a, c], [b, c, a], [c, a, b], [c, b , una]].
Estoy leyendo esto aquí http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations
Pero Wikipedia nunca ha sido bueno para explicar. No entiendo mucho de eso.
algorithm
list
permutation
fingir
fuente
fuente
Respuestas:
Básicamente, para cada elemento de izquierda a derecha, se generan todas las permutaciones de los elementos restantes (y cada uno se agrega con los elementos actuales). Esto se puede hacer de forma recursiva (o iterativa si le gusta el dolor) hasta que se alcanza el último elemento, momento en el que solo hay un orden posible.
Entonces, con la lista [1,2,3,4] se generan todas las permutaciones que comienzan con 1, luego todas las permutaciones que comienzan con 2, luego 3 y luego 4.
Esto reduce efectivamente el problema de encontrar permutaciones de una lista de cuatro elementos a una lista de tres elementos. Después de reducir a 2 y luego a 1 listas de elementos, se encontrarán todos.
Ejemplo que muestra permutaciones de proceso usando 3 bolas de colores:
(de https://en.wikipedia.org/wiki/Permutation#/media/File:Permutations_RGB.svg - https://commons.wikimedia.org/wiki/File:Permutations_RGB. svg )
fuente
Aquí hay un algoritmo en Python que funciona en su lugar en una matriz:
Puede probar el código usted mismo aquí: http://repl.it/J9v
fuente
Ya hay muchas buenas soluciones aquí, pero me gustaría compartir cómo resolví este problema por mi cuenta y espero que esto pueda ser útil para alguien que también quisiera derivar su propia solución.
Después de reflexionar un poco sobre el problema, he llegado a las siguientes dos conclusiones:
L
de tamañon
habrá igual número de soluciones comenzando con L 1 , L 2 ... L n elementos de la lista. Dado que en total hayn!
permutaciones de la lista de tamañon
, obtenemosn! / n = (n-1)!
permutaciones en cada grupo.[a,b]
y[b,a]
.Usando estas dos ideas simples, he derivado el siguiente algoritmo:
Así es como implementé esto en C #:
fuente
La respuesta de Wikipedia para "orden lexicográfico" me parece perfectamente explícita en el estilo de un libro de cocina. ¡Cita un origen del algoritmo en el siglo XIV!
Acabo de escribir una implementación rápida en Java del algoritmo de Wikipedia como verificación y no fue un problema. Pero lo que tienes en tu Q como ejemplo NO es "enumerar todas las permutaciones", sino "una LISTA de todas las permutaciones", por lo que wikipedia no te será de mucha ayuda. Necesita un lenguaje en el que se puedan construir listas de permutaciones. Y créanme, las listas de unos pocos miles de millones no suelen manejarse en lenguajes imperativos. Realmente desea un lenguaje de programación funcional no estricto, en el que las listas sean un objeto de primera clase, para sacar cosas sin acercar la máquina a la muerte térmica del Universo.
Eso es fácil. En Haskell estándar o cualquier lenguaje FP moderno:
y
fuente
Como dijo WhirlWind, comienzas por el principio.
Cambia el cursor con cada valor restante, incluido el cursor en sí, todas estas son instancias nuevas (usé una
int[]
yarray.clone()
en el ejemplo).Luego, realice permutaciones en todas estas listas diferentes, asegurándose de que el cursor esté a la derecha.
Cuando no queden más valores (el cursor está al final), imprima la lista. Ésta es la condición de parada.
fuente
Recursivo siempre requiere un esfuerzo mental para mantenerlo. Y para números grandes, el factorial es fácilmente enorme y el desbordamiento de la pila fácilmente será un problema.
Para números pequeños (3 o 4, que se encuentran principalmente), los bucles múltiples son bastante simples y directos. Es lamentable que las respuestas con bucles no se voten.
Comencemos con la enumeración (en lugar de la permutación). Simplemente lea el código como código pseudo Perl.
La enumeración se encuentra con más frecuencia que la permutación, pero si se necesita permutación, simplemente agregue las condiciones:
Ahora, si realmente necesita un método general potencialmente para listas grandes, podemos usar el método radix. Primero, considere el problema de enumeración:
El incremento de la raíz es esencialmente un conteo de números (en la base del número de elementos de la lista).
Ahora, si necesita permutaciones, simplemente agregue los cheques dentro del ciclo:
Editar: el código anterior debería funcionar, pero para la permutación, radix_increment podría ser un desperdicio. Entonces, si el tiempo es una preocupación práctica, tenemos que cambiar radix_increment a permute_inc:
Por supuesto que ahora este código es lógicamente más complejo, lo dejo para el ejercicio del lector.
fuente
Referencia: Geeksforgeeks.org
fuente
Si alguien se pregunta cómo se hace la permutación en javascript.
Idea / pseudocódigo
por ejemplo. 'a' + permutar (bc). permuta de bc sería bc & cb. Ahora agregue estos dos y dará abc, acb. de manera similar, elija b + permute (ac) proporcionará bac, bca ... y continuará.
ahora mira el código
Tómate tu tiempo para entender esto. Obtuve este código de ( pertumación en JavaScript )
fuente
Otro en Python, no está en su lugar como @ cdiggins, pero creo que es más fácil de entender
fuente
Estaba pensando en escribir un código para obtener las permutaciones de cualquier entero dado de cualquier tamaño, es decir, proporcionando un número 4567 obtenemos todas las permutaciones posibles hasta 7654 ... Así que trabajé en él y encontré un algoritmo y finalmente lo implementé, aquí es el código escrito en "c". Simplemente puede copiarlo y ejecutarlo en cualquier compilador de código abierto. Pero algunos defectos esperan ser depurados. Por favor aprecie.
Código:
fuente
Yo creé este. basado en la investigación también permutate (qwe, 0, qwe.length-1); Para que lo sepas, puedes hacerlo con o sin retroceso
fuente
Aquí hay un método de juguete Ruby que funciona así
#permutation.to_a
podría ser más legible para los locos. Es muy lento, pero también 5 líneas.fuente
He escrito esta solución recursiva en ANSI C. Cada ejecución de la función Permutate proporciona una permutación diferente hasta que se completan todas. Las variables globales también se pueden utilizar para variables de hecho y recuento.
fuente
Versión de Java
P.ej
salida:
fuente
en PHP
fuente
Aquí está el código en Python para imprimir todas las posibles permutaciones de una lista:
He usado un algoritmo de orden lexicográfico para obtener todas las permutaciones posibles, pero un algoritmo recursivo es más eficiente. Puede encontrar el código para el algoritmo recursivo aquí: permutaciones de recursividad de Python
fuente
fuente
En Scala
fuente
esta es una versión java para permutación
fuente
Aquí hay una implementación para ColdFusion (requiere CF10 debido al argumento de fusión de ArrayAppend ()):
Basado en la solución js de KhanSharp anterior.
fuente
Sé que este es un tema muy antiguo e incluso fuera de tema en el stackoverflow de hoy, pero aún quería contribuir con una respuesta de JavaScript amigable por la sencilla razón de que se ejecuta en su navegador.
También agregué el
debugger
punto de interrupción de la directiva para que pueda recorrer el código (se requiere Chrome) para ver cómo funciona este algoritmo. Abra su consola de desarrollo en Chrome (F12
en Windows oCMD + OPTION + I
en Mac) y luego haga clic en "Ejecutar fragmento de código". Esto implementa exactamente el mismo algoritmo que @WhirlWind presentó en su respuesta.Su navegador debería pausar la ejecución en la
debugger
directiva. ÚseloF8
para continuar con la ejecución del código.¡Repase el código y vea cómo funciona!
fuente
En la siguiente solución de Java, aprovechamos el hecho de que las cadenas son inmutables para evitar la clonación del conjunto de resultados en cada iteración.
La entrada será una cadena, diga "abc", y la salida serán todas las posibles permutaciones:
Código:
Se puede aplicar el mismo enfoque a las matrices (en lugar de una cadena):
fuente
Es mi solución en Java:
fuente
Realmente no se puede hablar de resolver un problema de permultación en recursividad sin publicar una implementación en un (dialecto de) idioma que fue pionero en la idea . Entonces, en aras de la integridad, esta es una de las formas en que se puede hacer en Scheme.
llamando
(permof (list "foo" "bar" "baz"))
obtendremos:No entraré en los detalles del algoritmo porque se ha explicado lo suficiente en otras publicaciones. La idea es la misma.
Sin embargo, los problemas recursivos tienden a ser mucho más difíciles de modelar y pensar en medios destructivos como Python, C y Java, mientras que en Lisp o ML se pueden expresar de manera concisa.
fuente
Aquí hay una solución recursiva en PHP. La publicación de WhirlWind describe con precisión la lógica. Vale la pena mencionar que la generación de todas las permutaciones se ejecuta en tiempo factorial, por lo que podría ser una buena idea utilizar un enfoque iterativo.
La función strDiff toma dos cadenas,
s1
ys2
, y devuelve una nueva cadena con todos1
sin elementos ens2
(materia duplicada). Entonces,strDiff('finish','i')
=>'fnish'
(la segunda 'i' no se elimina).fuente
Aquí hay un algoritmo en R, en caso de que alguien necesite evitar cargar bibliotecas adicionales como tuve que hacerlo.
Uso de ejemplo:
fuente
fuente
Este es un código recursivo para java, la idea es tener un prefijo que agregue el resto de los caracteres:
Ejemplo:
Entrada = "ABC"; Salida:
ABC ACB BAC BCA CAB CBA
fuente
str
cuando se llama de forma recursiva, de lo contrario no terminará.Solo para completar, C ++
...
fuente
Aquí hay una solución no recursiva en C ++ que proporciona la siguiente permutación en orden ascendente, de manera similar a la funcionalidad proporcionada por std :: next_permutation:
fuente