2011-12-16 23 views
15

Dada una matriz de int, cada int aparece exactamente DOS VECES en la matriz . Encuentre y devuelva el int tal que este par de int tenga la distancia máxima de entre sí en esta matriz.Encuentra el elemento con la distancia más larga en una matriz determinada donde cada elemento aparece dos veces?

p. Ej. [2, 1, 1, 3, 2, 3]

2: d = 5-1 = 4; 
1: d = 3-2 = 1; 
3: d = 6-4 = 2; 
return 2 

Mis ideas:

Uso HashMap, la clave es a[i], y el valor es el índice. Escanee el a[], ponga cada número en hash. Si un número es golpeado dos veces, use su índice menos el índice de números antiguos y use el resultado para actualizar el valor del elemento en hash.

Después de eso, escanear hash y devolver la llave con el elemento más grande (distancia). es O (n) en tiempo y espacio.

Como hacerlo en tiempo O (n) y O (1) el espacio?

+1

Creo que puede hacerlo más rápido ... solo una pista: en su ejemplo, después de encontrar que para 'a [0]' la distancia es '5', no necesita verificar más valores en absoluto, ya que el tamaño si el conjunto es '6'. – lapk

+3

@AzzA Eso acelera las cosas con seguridad, sin embargo, no afecta la tasa de crecimiento asintótico lineal. –

+0

¿Es esta una pregunta de entrevista? –

Respuesta

2

¿Le gustaría tener la máxima distancia, así que supongo que el número se busca una mayor probabilidad de estar en el inicio y el fin. Esta es la razón por la que pasaría por encima de la matriz desde el inicio hasta el final al mismo tiempo.

[2, 1, 1, 3, 2, 3] 
Check if 2 == 3? 
Store a map of numbers and position: [2 => 1, 3 => 6] 
Check if 1 or 2 is in [2 => 1, 3 => 6] ? 

Lo sé, eso ni siquiera es pseudocódigo y no está completo, pero solo para dar a conocer la idea.

+0

Almacenar un mapa implicaría que no está utilizando el espacio 'O (1)', ya que el tamaño del mapa depende de la cantidad de elementos distintos de la lista. La pregunta ya consideró el uso de una tabla de búsqueda. – birryree

+0

Sí, en teoría si solo observa O(). Pero en la práctica, este es más rápido y usa menos espacio. Él _siempre_ crea un mapa sobre toda la matriz. – PiTheNumber

+0

La suposición es algo falaz: supongamos que solo tiene pares "bien educados", excepto por un golpe levemente mal llevado en el medio: '[1, 2, 1, 3, 2, 4, 4, 5, 3, 6, 5, 6] '. Aquí '3' no es especialmente en ningún extremo. –

0

índice de Conjunto iLeft al primer elemento, el índice iRight al segundo elemento. Incremente el índice de iRight hasta que encuentre una copia del elemento de la izquierda o encuentre el final de la matriz. En el primer caso, recuerda la distancia.

Incremento iLeft. Comience a buscar desde nuevo iRight. El valor de inicio de iRight nunca disminuirá. código Delphi:

iLeft := 0; 
    iRight := 1; 

    while iRight < Len do begin //Len = array size 
    while (iRight < Len) and (A[iRight] <> A[iLeft]) do 
     Inc(iRight); //iRight++ 
    if iRight < Len then begin 
     BestNumber := A[iLeft]; 
     MaxDistance := iRight - iLeft; 
    end; 
    Inc(iLeft); //iLeft++ 
    iRight := iLeft + MaxDistance; 
    end; 
+1

[1, 2, 2, 1, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3]: en este caso después de encontrar iLeft == 0, iRight == 3, comenzará buscando un par para iLeft == 1. Pero como iRight nunca se reducirá, nunca encontrará iRight == 2 ... por lo que irá al final de la matriz. O tal vez no entiendo el algoritmo exactamente ... – liori

+0

@liori 'iRight' se restablece (' iRight = iLeft + MaxDistance') al final de cada ciclo. Entonces 'iRight' disminuye. El par de '2' no se encontrará en su ejemplo, pero este algoritmo debería poder dar el resultado correcto. Pero como 'iRight' disminuye, dudo si es O (n). – fefe

+0

@fefe Sí, O (n) es mi error.Remoto. – MBo

0

Este algoritmo es O (1) espacio (con algo de trampa), O (n) tiempo (promedio), necesita la matriz de origen para ser no-const y lo destruye al final. También limita los valores posibles en la matriz (se deben reservar tres bits de cada valor para el algoritmo).

La mitad de la respuesta ya está en la pregunta. Usa hashmap. Si un número es golpeado dos veces, use la diferencia de índice, actualice el mejor resultado hasta ahora y elimine este número del hashmap para liberar espacio. Para convertirlo en O (1) espacio, simplemente reutilice la matriz fuente. Convierta la matriz a hashmap en contexto.

Antes de pasar un elemento de matriz a la célula HashMap, recuerde su valor y posición. Después de esto, puede sobrescribirse de manera segura. Luego use este valor para calcular una nueva posición en el hashmap y sobrescribirlo. Los elementos se mezclan de esta manera hasta que se encuentra una celda vacía. Para continuar, seleccione cualquier elemento que no esté reordenado. Cuando se reordena todo, cada int pair es definitivamente golpeado dos veces, aquí tenemos un hashmap vacío y un mejor valor de resultado actualizado.

Un bit reservado se utiliza mientras que la conversión elementos de la matriz a las células HashMap. Al principio está despejado. Cuando se reordena un valor a la celda hashmap, este bit se establece. Si este bit no está configurado para el elemento sobreescrito, este elemento simplemente se procesa para ser procesado a continuación. Si este bit está configurado para que se sobrescriba el elemento, aquí hay un conflicto, elija el primer elemento no utilizado (con este bit no configurado) y sobrescríbalo en su lugar.

2 bits más reservados se utilizan para encadenar valores conflictivos. Codifican las posiciones donde la cadena se inicia/finaliza/continúa. (Es posible optimizar este algoritmo para que solo se necesiten 2 bits reservados ...)

Una celda hashmap debe contener estos 3 bits reservados, el índice del valor original y cierta información para identificar este elemento de forma exclusiva. Para que esto sea posible, una función hash debe ser reversible para que parte del valor pueda restaurarse dada su posición en la tabla. En el caso más simple, la función hash es solo ceil(log(n)) bits menos significativos. Valor de la tabla consta de 3 campos:

  • 3 bits reservados
  • 32 - 3 - (ceil(log(n))) bits de orden superior del valor original
  • ceil(log(n)) bits para la posición de los elementos de la matriz original

Complejidad de tiempo es O (n) solo en promedio; la complejidad del peor caso es O (n^2).

Otra variante de este algoritmo es transformar la matriz a hashmap secuencialmente: en cada paso m teniendo 2^m primeros elementos de la matriz convertidos a hashmap. Algunas matrices de tamaño constante se pueden intercalar con el hashmap para mejorar el rendimiento cuando m es bajo. Cuando m es alto, debe haber suficientes pares int, que ya están procesados ​​y ya no necesitan espacio.

+0

gracias por su análisis detallado, pero ¿cómo mantener el hash ksys? porque tienes que usar la tecla hash para buscar en la tabla hash y comprobar si un elemento nuevo se golpea dos veces. – user1002288

+0

La mitad de la clave hash se almacena en la tabla hash (bits de orden superior). La otra mitad se restablece desde la posición en la tabla hash (porque la función hash es reversible). Por ejemplo, el tamaño de la tabla es 32 y busca el número 33. Tome los bits de orden baja (1), de modo que el índice en la tabla sea 1. Compare los bits de orden superior en este elemento de la tabla con los bits de orden superior del número (32). Si no hay coincidencia, siga la cadena de valores conflictivos. Si 32 se encuentra en algún lugar de la cadena, este elemento se golpea dos veces. Si no se encuentra, agréguelo al hashmap. –

+0

En otras palabras, parte de la clave hash se usa para encontrar la entrada correcta de hashmap (y no se almacena en ningún lugar porque no es necesaria para resolver colisiones). Otra parte de la clave hash se usa para resolver posibles colisiones (y se almacena en cada entrada de hashmap). –

0

No hay forma de hacerlo en el tiempo O (n) y en el espacio O (1).

Cuestiones relacionadas