Dados los pares ‘n1’ de corchetes “[]”, los pares ‘n2’ de corchetes “{}” y los pares ‘n3’ de corchetes “()”, ¿cómo podemos encontrar todas las combinaciones válidas posibles de todos estos pares de manera eficiente?

Consideremos la estructura general de cualquier paréntesis válido. Cualquier estructura necesariamente tendrá un prefijo más corto que sea un paréntesis válido (que puede ser el paréntesis completo). Aprovecharemos este hecho para calcular todas las paréntesis válidas de manera eficiente.

Digamos que la función que queremos implementar es GenerateAllParenthesizations. También implementaremos otra función, que llamaremos GeneratePrefixFreeParenthesization. Aquí están las especificaciones para ambas funciones:

GenerateAllParenthesizations tomará los números de símbolos dados y devolverá todos los paréntesis válidos de las cantidades de símbolos especificadas.

GeneratePrefixFreeParenthesization tomará el número dado de símbolos y devolverá todos los paréntesis válidos de las cantidades especificadas de símbolos que no tienen un prefijo más corto que sea válido.

Consideremos esta segunda función primero. ¿Qué sabemos sobre tal paréntesis? Bueno, si hay corchetes, el primer carácter debe ser un corchete de apertura y el último carácter debe ser un corchete de cierre. Si este no fuera el caso, entonces los corchetes se encontrarán inválidamente dentro de otros corchetes o habrá un prefijo más corto que es un paréntesis válido. Podemos derivar una regla similar si no hay corchetes, pero hay corchetes. Si solo hay paréntesis, el primer y el último carácter deben ser un paréntesis de apertura y un paréntesis de cierre, respectivamente. Una vez que se establecen esos caracteres, podemos generar arbitrariamente paréntesis con los símbolos restantes.

Ahora, volvamos a la primera función. Sabemos que cada paréntesis válido debe tener un prefijo más corto. Por lo tanto, aplicaremos la fuerza bruta sobre todas las [matemáticas] (n_1 + 1) (n_2 + 1) (n_3 + 1) -1 [/ matemáticas] posibles recuentos de paréntesis que debe tener el prefijo más corto y usaremos GeneratePrefixFreeParenthesization para obtener todos esos prefijos Mientras tanto, podemos generar paréntesis válidos arbitrarios con los símbolos restantes, por lo que llamamos recursivamente GenerateAllParenthesizations con los recuentos restantes.

Esto elimina los pasos recursivos. La última parte es averiguar el caso base de GenerateAllParenthesizations – si no hay símbolos, entonces tenemos una cadena vacía.

Tendremos que memorizar los resultados de las llamadas anteriores para la eficiencia.

Una idea simple es DP: el estado es una tupla de 6 con el número de llaves de apertura de cada tipo a la izquierda y el número de llaves abiertas de cada tipo. En la transición de estado, cerramos una llave abierta o colocamos una nueva. Entonces la complejidad es O (n1 ^ 2 * n2 ^ 2 * n3 ^ 2)

El número catalán Cn cuenta el número de expresiones que contienen n pares de paréntesis que coinciden correctamente para (). Aquí hay 3 tipos de nombres de paréntesis [], (), {}
Hay n1 pares de ‘[]’. Hay n2 pares de ‘{}’. Hay n3 pares de ‘()’.
C (2n, n) / (n + 1) proporciona la combinación válida para cualquier par.
Supongamos que todos los paréntesis fueran el mismo símbolo, digamos []

Por lo tanto, C (2n1 + 1,2n2 + 1,2n3 + 1, n1 + n2 + n3) / (n1 + n2 + n3 + 1) formas de emparejar n1, n2, n3 pares de paréntesis.

Fuera de esto, hay C (n1 + n2 + n3, n1) formas de transformar [] de nuevo a ().
Ahora del resto hay formas C (n2 + n3, n1) de transformar [] a {}.

Las formas totales de emparejamiento son por lo tanto

C (2n1 + 1,2n2 + 1,2n3 + 1, n1 + n2 + n3) / (n1 + n2 + n3 + 1) * C (n1 + n2 + n3, n1) * C (n2 + n3, n1)

More Interesting

¿Son los sentimientos la función del costo del algoritmo de aprendizaje automático de los humanos?

¿Cuál es la intuición detrás del algoritmo de clasificación rápida de múltiples claves?

¿Por qué es Introducción a los algoritmos una lectura obligada para convertirse en un mejor programador?

Cuando quitamos un borde de un árbol, parece obvio que nos quedan dos árboles, pero ¿cómo podríamos probar esto?

¿Cuál es el mejor algoritmo para elegir para la tarea de aprendizaje automático de agrupar una base de datos de listados de casas con sus propiedades (algunos de los cuales son binarios y otros son numéricos y preferiblemente con la primera imagen)?

¿Cuál es el enfoque de este problema algorítmico a continuación?

¿Cuáles son los usos prácticos de 2-3 árboles o árboles rojo-negros?

¿Cómo se debe decidir sobre un clasificador / algoritmo óptimo para usar en un conjunto de datos en particular?

¿Cuál es la diferencia entre los algoritmos de programación de tareas y los algoritmos de equilibrio de carga (estáticos y dinámicos)?

¿Cómo se puede usar un algoritmo genético para clasificar las soluciones candidatas?

¿Por qué la complejidad temporal del siguiente código O (logn)?

Si uno se está preparando para una entrevista en Google (y tiene 6 meses en la mano), ¿qué libro lo beneficiará más y por qué? ¿'Introducción a los algoritmos' (CLRS) o 'Algoritmos desbloqueados'?

¿Cuál es la diferencia entre un gráfico y un árbol en estructuras de datos y algoritmos?

¿Cómo la elección incorrecta de las estructuras de datos hace que un programa sea ineficiente?

Cómo crear una matriz de intervalos de fechas a partir de una matriz de fechas estáticas en JavaScript