Quiero probar o refutar la existencia de un algoritmo que, dada una matriz de enteros, encuentra tres índices y manera que y (o encuentra que no existe tal triple) en tiempo lineal.
Esta no es una pregunta de tarea; Lo vi en un foro de programación enmarcado como "tratar de implementar dicho algoritmo". Sospecho que es imposible después de varios experimentos. Mi intuición me lo dice, pero eso realmente no cuenta para nada.
Me gustaría demostrarlo formalmente. ¿Cómo lo haces? Idealmente, me gustaría ver una prueba presentada paso a paso, y luego, si está tan inclinado, alguna explicación sobre cómo probar / refutar preguntas simples como esta en general. Si ayuda, algunos ejemplos:
[1,5,2,0,3] → (1,2,3)
[5,6,1,2,3] → (1,2,3)
[1,5,2,3] → (1,2,3)
[5,6,1,2,7] → (1,2,7)
[5,6,1,2,7,8] → (1,2,7)
[1,2,999,3] → (1,2,999)
[999,1,2,3] → (1,2,3)
[11,12,8,9,5,6,3,4,1,2,3] → (1,2,3)
[1,5,2,0,-5,-2,-1] → (-5,-2,-1)
Supuse que uno podría iterar sobre , y cada vez que hay un (nuestro actual , es decir), hacemos un nuevo triple y lo empujamos a una matriz. Continuamos dando un paso y comparando cada triple hasta que uno de nuestros triples esté completo. Así es como , ! Pero creo que esto es más complejo que el simple ya que el número de triples en nuestra matriz triple en el peor de los casos correspondería al tamaño de la lista de entrada.[1,5,2,0,-5,-2,-1] → 1..2.. -5.. -2.. -1
[1,5,2,0,-5,-2,3,-1] → 1..2.. -5.. -2.. 3
fuente
Respuestas:
Esta es la variación del problema de subsecuencia creciente más largo ; Esta es la solución presentada en Wikipedia utilizando dos matrices auxiliares y P :M P
Este algoritmo se ejecuta en el peor de los casos . Su problema es un caso especial que le permite regresar cuando L = 3, lo que empuja el tiempo de ejecución a O ( n ) porque la búsqueda binaria se ejecuta solo en matrices de longitud como máximo dos, que por lo tanto es en el tiempo O ( 1 ) en lugar de Θ ( log n ) en el caso general.Θ(nlogn) L=3 O(n) O(1) Θ(logn)
Considere el pseudocódigo modificado:
fuente
Una nota sobre metodología
Pensé un poco en este problema y llegué a una solución. Cuando leí la respuesta de Saeed Amiri , me di cuenta de que se me ocurrió una versión especializada del algoritmo estándar de búsqueda de subsecuencias más largo para una secuencia de longitud 3. Estoy publicando la forma en que se me ocurrió la solución, porque creo que Es un ejemplo interesante de resolución de problemas.
La versión de dos elementos.
Comencemos con algo pequeño: en lugar de buscar tres índices en los que los elementos estén en orden, busquemos dos: tal que A [ i ] < A [ j ] .i < j A [ i ] < A [ j ]
Si está disminuyendo (es decir, ∀ i < j , A [ i ] ≥ A [ j ] , o de manera equivalente ∀ i , A [ i ] ≥ A [ i + 1 ] , entonces no existen tales índices. De lo contrario, hay un índice i tal que A [ i ] < A [ i + 1 ] .UNA ∀ i < j , A [ i ] ≥ A [ j ] ∀ i , A [ i ] ≥ A [ i + 1 ] yo A [ i ] < A [ i + 1 ]
Este caso es muy simple; Intentaremos generalizarlo. Muestra que el problema tal como se indicó no tiene solución: los índices solicitados no siempre existen. Por lo tanto, pediremos más bien que el algoritmo devuelva índices válidos, si existen, o afirme correctamente que no existen tales índices.
Subiendo con el algoritmo
Usaré el término subsecuencia para significar un extracto de la matriz consiste en índices que pueden no ser consecutivos ( ( A [ i 1 ] , … , A [ i m ] ) con i 1 < ⋯ < i m ), y ejecutaré significa elementos consecutivos de A ( ( A [ i ] , A [ i + 1 ] , … , A [UNA ( A [ i1] , ... , A [ imetro] ) yo1< ⋯ < imetro UNA ).(A[i],A[i+1],…,A[i+m−1])
Acabamos de ver que los índices solicitados no siempre existen. Nuestra estrategia será estudiar cuando los índices no existen. Haremos esto suponiendo que estamos tratando de encontrar los índices y viendo cómo nuestra búsqueda podría salir mal. Entonces, los casos en los que la búsqueda no sale mal proporcionarán un algoritmo para encontrar los índices.
Con dos índices, podríamos encontrar índices consecutivos. Con tres índices, es posible que no podamos encontrar y k = j + 1 . Sin embargo, podemos considerar el caso cuando hay una serie de tres elementos estrictamente crecientes ( A [ i ] < A [ i + 1 ] < A [ i + 2 ] ) por resolver, ya que es fácil reconocer tales series, y vea cómo esta condición podría no cumplirse. Suponga que la secuencia no tiene una ejecución estrictamente creciente de longitud 3.j = i + 1 k = j + 1 A [ i ] < A [ i + 1 ] < A [ i + 2 ]
La secuencia solo tiene carreras estrictamente crecientes de longitud 2 (que llamaré pares ordenados para abreviar), separadas por una carrera decreciente de longitud al menos 2. Para una carrera estrictamente creciente para formar parte de una secuencia creciente de 3 elementos, debe haber un elemento anterior i tal que A [ i ] < A [ j ] o un elemento posterior k tal que A [ j + 1 ] < A [ kA [ j ] < A [ j + 1 ] yo A [ i ] < A [ j ] k .A [ j + 1 ] < A [ k ]
Un caso en el que ni ni k existe es cuando cada par ordenado es completamente inferior al siguiente. Esto no es todo: cuando los pares están entrelazados, necesitamos compararlos más finamente.yo k
El elemento más a la izquierda de una subsecuencia creciente necesita llegar temprano y ser pequeño. El siguiente elemento j debe ser más grande, pero lo más pequeño posible para poder encontrar un tercer elemento más grande k . El primer elemento i no siempre es el elemento más pequeño de la secuencia, y tampoco es siempre el primero para el que hay un elemento posterior más grande, a veces hay una subsecuencia inferior de 2 elementos más adelante, y a veces hay una mejor apto para el mínimo ya encontrado.yo j k yo
Declaración del algoritmo
Dado en la sintaxis de Python, pero tenga en cuenta que no lo he probado.
Bosquejo de prueba
index1
es el índice del mínimo de la parte de la matriz que ya se ha atravesado (si ocurre varias veces, conservamos la primera aparición) oNone
antes de procesar el primer elemento.index2
almacena los índices de la subsecuencia creciente de longitud 2 en la parte ya atravesada de la matriz que tiene el elemento más grande más bajo, oNone
si tal secuencia no existe.Cuando se
return (index2[0], index2[1], i)
ejecuta, tenemosvalue2[0] < value[1]
(esto es una invariante devalue2
) yvalue[1] < A[i]
(obvio por el contexto). Si el ciclo termina sin invocar el retorno temprano, tampocovalue1 == None
, en cuyo caso no hay subsecuencia creciente de longitud 2 y mucho menos 3, ovalue1
contiene la subsecuencia creciente de longitud 2 que tiene el elemento más grande más bajo. En el último caso, además tenemos la invariante de que ninguna subsecuencia creciente de longitud 3 termina antes quevalue1
; por lo tanto, el último elemento de cualquiera de esas subsecuencias, sumado avalue2
, formaría una subsecuencia creciente de longitud 3: como también tenemos el invariante quevalue2
no es parte de una subsecuencia creciente de longitud 3 contenida en la parte ya atravesada de la matriz, allí no existe tal subsecuencia en toda la matriz.Probar los invariantes antes mencionados se deja como un ejercicio para el lector.
Complejidad
Prueba formal
A la izquierda como ejercicio para el lector.
fuente
Primero, recorra la matriz de izquierda a derecha manteniendo una pila y una matriz auxiliar que le indica para cada elemento, el índice de un elemento mayor que él y a la derecha del mismo.
Inicialmente, la pila está vacía y la matriz auxiliar contiene todos- 1 s.
Cada vez que considera un nuevo elemento en la matriz, si ese elemento es mayor que el elemento superior de la pila, lo saca de la pila y establece el elemento de matriz auxiliar correspondiente a la parte superior para tener el índice del nuevo elemento debajo consideración.
Continúe sacando elementos de la pila y estableciendo el índice correspondiente, mientras que el elemento actual es mayor. Una vez que la parte superior tiene un elemento que no es menor (o se vacía), empuje el elemento actual hacia la pila y continúe con el siguiente elemento de la matriz, repitiendo el paso anterior.
Haga otra pasada (y otra matriz auxiliar), pero vaya de derecha a izquierda.
Pase por las matrices auxiliares y elija una posición donde las dos entradas correspondientes en la matriz no estén- 1 .
Dado que considera cada elemento de la matriz solo un número constante de veces, esto esO ( n ) hora.
Creo que también puedes deshacerte de las pilas (considerando "máximos de sufijo" y "mínimos de prefijo"), pero las pilas te dan los elementos más cercanos. Entonces, si quisieras minimizar decirk - i , podrías usar las pilas.
El pseudocódigo para la primera pasada podría verse así:
fuente