Me lo pidieron en una entrevista y esta es la solución que proporcioné:
public static int[] merge(int[] a, int[] b) {
int[] answer = new int[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length)
{
if (a[i] < b[j])
{
answer[k] = a[i];
i++;
}
else
{
answer[k] = b[j];
j++;
}
k++;
}
while (i < a.length)
{
answer[k] = a[i];
i++;
k++;
}
while (j < b.length)
{
answer[k] = b[j];
j++;
k++;
}
return answer;
}
¿Hay una manera más eficiente de hacer esto?
Editar: métodos de longitud corregida.
while (i < a.length && j < b.length) answer[k++] = a[i] < b[j] ? a[i++] : b[j++];
Especificación del lenguaje Java: ¿Operador condicional? : .Respuestas:
Una mejora menor, pero después del ciclo principal, puede usar
System.arraycopy
para copiar la cola de cualquiera de las matrices de entrada cuando llegue al final de la otra. SinO(n)
embargo, eso no cambiará las características de rendimiento de su solución.fuente
¡Es un poco más compacto pero exactamente igual!
fuente
Me sorprende que nadie haya mencionado esta implementación mucho más genial, eficiente y compacta:
Puntos de interes
System.arraycopy
ganarían porque internamente puede hacerlo con una sola instrucción de ensamblaje x86.a[i] >= b[j]
lugar dea[i] > b[j]
. Esto garantiza la "estabilidad" que se define como cuando los elementos de a y b son iguales, queremos elementos de a antes de b.fuente
j < 0
,b
ya está agotado, por lo que seguimos agregando losa
elementos restantes a laanswer
matrizCualquier mejora que se pueda hacer sería micro optimizaciones, el algoritmo general es correcto.
fuente
System.arrayCopy()
es estúpidamente rápido ya que utilizamemcpy
llamadas optimizadas para CPU . Por lo tanto, hay margen para mejorar el rendimiento copiando fragmentos. También hay margen para la búsqueda binaria de los límites.Esta solución también es muy similar a otras publicaciones, excepto que usa System.arrayCopy para copiar los elementos restantes de la matriz.
fuente
Aquí está la función actualizada. Elimina duplicados, es de esperar que alguien encuentre esto útil:
fuente
Se puede hacer en 4 declaraciones como a continuación
fuente
sort
función no puede usarse por sí misma como método de clasificación. Eso sería una regresión infinita en lugar de una recursión. También la otra premisa es que merge_array es la función que implementa la ordenación. Por lo tanto, esta respuesta es inutilizable en el contexto más probable.Tuve que escribirlo en JavaScript, aquí está:
fuente
Las colecciones de Apache admiten el método de clasificación desde la versión 4; puedes hacer esto usando el
collate
método en:Aquí cita de javadoc:
¡No reinventes la rueda! Referencia del documento: http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
fuente
Combinación de GallopSearch: O (log (n) * log (i)) en lugar de O (n)
Seguí adelante e implementé la sugerencia de barba gris en los comentarios. Principalmente porque necesitaba una versión de misión crítica altamente eficiente de este código.
Esta debería ser la forma más eficiente de hacerlo, con la complejidad temporal de O (log (n) * log (i)) en lugar de O (n). Y en el peor de los casos, la complejidad del tiempo de O (n). Si sus matrices son grumosas y tienen largas cadenas de valores juntas, esto eclipsará cualquier otra forma de hacerlo, de lo contrario, será mejor que ellas.
Tiene dos valores de lectura en los extremos de la matriz de fusión y el valor de escritura dentro de la matriz de resultados. Después de descubrir cuál es el valor final es menor, realiza una búsqueda de galope en esa matriz. 1, 2, 4, 8, 16, 32, etc. Cuando encuentra el rango donde el valor de lectura de la otra matriz es mayor. Realiza búsquedas binarias en ese rango (corta el rango a la mitad, busca la mitad correcta, repite hasta un solo valor). Luego, la matriz copia esos valores en la posición de escritura. Teniendo en cuenta que la copia, por necesidad, se mueve de modo que no pueda sobrescribir los mismos valores de la matriz de lectura (lo que significa que la matriz de escritura y la matriz de lectura pueden ser las mismas). Luego realiza la misma operación para la otra matriz que ahora se sabe que es menor que el nuevo valor de lectura de la otra matriz.
Esta debería ser la forma más eficiente de hacerlo.
Algunas respuestas tenían una capacidad de eliminación duplicada. Eso requerirá un algoritmo O (n) porque en realidad debes comparar cada elemento. Así que aquí hay una aplicación independiente para eso, que se aplicará después del hecho. No puede galopar a través de múltiples entradas por completo si necesita verlas todas, aunque podría galopar a través de los duplicados, si tuviera muchos de ellos.
Actualización: respuesta anterior, no es un código horrible, pero claramente inferior al anterior.
Otra innecesaria hiper-optimización. No solo invoca arraycopy para los bits finales, sino también para el comienzo. Procesar cualquier no solapamiento introductorio en O (log (n)) mediante una búsqueda binaria en los datos. O (log (n) + n) es O (n) y en algunos casos el efecto será bastante pronunciado, especialmente cuando no hay superposición entre las matrices de fusión.
fuente
That is totally what the implemented Arrays.sort does
( Eso : desde la primera revisión de su respuesta, o desde mi comentario del 19 de febrero), tampoco puede encontrarlo en el JDK 8 de Sunsoft: ¿a qué implementaciónArrays.sort
se refiere?Aquí hay un formulario abreviado escrito en javascript:
fuente
fuente
a[mid+1 .. hi]
aaux
de?Creo que la introducción de la lista de omisión para la matriz ordenada más grande puede reducir el número de comparaciones y puede acelerar el proceso de copia en la tercera matriz. Esto puede ser bueno si la matriz es demasiado grande.
fuente
fuente
fuente
for (int i, j, k = i = j = 0 ; k < c.length ; ) c[k++] = b.length <= j || i < a.length && a[i] < b[j] ? a[i++] : b[j++];
. ¿Cómo difiere de la respuesta de Andrew 2014 ?Algoritmo podría mejorarse de muchas maneras. Por ejemplo, es razonable verificar si
a[m-1]<b[0]
ob[n-1]<a[0]
. En cualquiera de esos casos, no hay necesidad de hacer más comparaciones. Algoritmo podría simplemente copiar matrices de origen en el resultante en el orden correcto.Las mejoras más complicadas pueden incluir la búsqueda de partes entrelazadas y ejecutar el algoritmo de fusión solo para ellas. Podría ahorrar mucho tiempo, cuando los tamaños de las matrices combinadas difieren en decenas de veces.
fuente
Este problema está relacionado con el algoritmo mergesort, en el que dos sub-matrices ordenadas se combinan en una sola sub-matriz ordenada. El libro CLRS da un ejemplo del algoritmo y limpia la necesidad de verificar si se ha alcanzado el final agregando un valor centinela (algo que se compara y "mayor que cualquier otro valor") al final de cada matriz.
Escribí esto en Python, pero también debería traducirse muy bien a Java:
fuente
Puede usar 2 hilos para llenar la matriz resultante, uno desde el frente, uno desde atrás.
Esto puede funcionar sin sincronización en el caso de los números, por ejemplo, si cada hilo inserta la mitad de los valores.
fuente
fuente
fuente
fuente
Mi lenguaje de programación favorito es JavaScript.
fuente
Tal vez use System.arraycopy
fuente
Salida es:
1, 2, 3, 4, 5, 6, 8, 9, 10, 100, 999, 1001,
fuente
arr2
notind2
, perotemp
.Puede usar operadores ternarios para hacer que el código sea un poco más compacto
fuente
Solo un poco diferente de la solución original
fuente
Para unir dos conjuntos ordenados en complejidad de tiempo O (m + n), utilice el siguiente enfoque con un solo bucle. myn es la longitud de la primera matriz y la segunda matriz.
fuente
fuente
Dado que la pregunta no asume ningún lenguaje específico. Aquí está la solución en Python. Suponiendo que las matrices ya están ordenadas.
Enfoque 1: uso de matrices numpy: importar numpy
Enfoque 2: uso de la lista, suponiendo que las listas estén ordenadas.
fuente
Since the question doesn't assume any specific language
desde 2011/5/11/19: 43, está etiquetado java ..sort()
esO(n log n)
en el mejor de los casosAquí está mi implementación de Java que elimina duplicados.
fuente