Encuentra el número más cercano en una matriz desordenada

Dada una gran variedad desordenada de long números aleatorios y un objetivo largo, ¿cuál es el algoritmo más eficiente para encontrar el número más cercano?

@Test
public void findNearest() throws Exception {
    final long[] numbers = {90L, 10L, 30L, 50L, 70L};
    Assert.assertEquals("nearest", 10L, findNearest(numbers, 12L));
}

preguntado el 31 de enero de 12 a las 08:01

¿Qué tal hacer una copia de la matriz, ordenarla y luego encontrar la más cercana? -

¿Te refieres al más cercano en general, al más grande más pequeño o al más pequeño más grande? -

@SavinoSguera más cercano de cualquier manera. -

8 Respuestas

Repita una vez a través de la matriz de longs. Almacene el número actual más cercano y la distancia a ese número. Continúe verificando cada número si está más cerca, y simplemente reemplace el número más cercano actual cuando encuentre un número más cercano.

Esto le da el mejor rendimiento de O (n).

La construcción de un árbol binario como lo sugiere otro respondedor tomará O (nlogn). Por supuesto, la búsqueda futura solo tomará O (logn) ... por lo que puede valer la pena si realiza muchas búsquedas.

Si eres un profesional, puedes paralelizar esto con openmp o biblioteca de subprocesos, pero supongo que eso está fuera del alcance de tu pregunta.

Respondido el 31 de enero de 12 a las 12:01

+1: ordenar la matriz también daría el mismo O (n log n) para ordenar y O (log n) para encontrar el más cercano, pero sería más eficiente en memoria (posiblemente también más rápido) - Peter Lawrey

De acuerdo, la clasificación sería más rápida debido a la ubicación de los datos. - James Cotter

@JamesCotter, por favor, explique la implementación paralelizada - Paul McKenzie

Si no tiene la intención de realizar múltiples solicitudes de este tipo en la matriz, no hay mejor manera que la verificación de tiempo lineal de fuerza bruta de cada número.

Si realiza varias solicitudes en la misma matriz, primero ordénelas y luego haga una búsqueda binaria en ellas, esto reducirá el tiempo para que dichas solicitudes lleguen a O (log (n)) pero aún paga el O (n * log (n )) para la clasificación, por lo que esto solo es razonable si el número de solicitudes es razonablemente grande, es decir, k * n >> (mucho más grande que) n * log (n) + k * log (n) donde k es el número de solicitudes .

Si la matriz va a cambiar, cree una árbol de búsqueda binaria y hacer una solicitud de límite inferior. De nuevo, esto solo es razonable si la solicitud de número más cercana es relativamente grande en comparación con las solicitudes de cambio de matriz y también con la cantidad de elementos. Como el costo de construcción del árbol es O (n * log (n)) y también el costo de actualización es O (logn), debe tener k * log (n) + n * log (n) + k * log (n) << (mucho más pequeño que) k * n

Respondido el 31 de enero de 12 a las 12:01

En mi humilde opinión, creo que deberías usar un Montón binario (http://en.wikipedia.org/wiki/Binary_heap) que tiene el tiempo de inserción de O (log n), siendo O (n log n) para toda la matriz. Para mí, lo mejor del montón binario es que se puede hacer dentro de su propia matriz, sin gastos generales. Echa un vistazo al sección heapfy.

Es posible "acumular" su matriz para obtener el elemento más grande / más bajo en O (1).

Respondido el 31 de enero de 12 a las 13:01

si construye un árbol de búsqueda binario a partir de sus números y busca en contra. O (log n) sería la complejidad en el peor de los casos. En su caso, no buscará la igualdad en su lugar, buscará el valor de retorno más pequeño a través de la resta.

Respondido el 31 de enero de 12 a las 12:01

Verificaría la diferencia entre los números mientras iteraba a través de la matriz y guardaría el valor mínimo para esa diferencia.

Si planea usar findNearest varias veces, calcularía la diferencia mientras clasifica (con un algoritmo de clasificación de complejidad n * log (n)) después de cada cambio de valores en esa matriz

Respondido el 31 de enero de 12 a las 12:01

El complejo de tiempo para hacer este trabajo es O (n), la longitud de los números.

    final long[] numbers = {90L, 10L, 30L, 50L, 70L};
    long tofind = 12L;
    long delta = Long.MAX_VALUE;
    int index = -1;
    int i = 0;
    while(i < numbers.length){
        Long tmp = Math.abs(tofind - numbers[i]);
        if(tmp < delta){
            delta = tmp;
            index = i;
        }
        i++;
    }

    System.out.println(numbers[index]); //if index is not -1

Pero Si desea encontrar muchas veces con valores diferentes, como 12L, contra la misma matriz de números, puede ordenar la matriz primero y la búsqueda binaria contra la matriz de números ordenados.

Respondido el 31 de enero de 12 a las 12:01

Si su búsqueda es única, puede particionar la matriz como en quicksort, usando el valor de entrada como pivote.

Si realiza un seguimiento, mientras realiza la partición, del elemento mínimo en la mitad derecha y el elemento máximo en la mitad izquierda, debe tenerlo en O (n) y una sola pasada sobre la matriz.

Yo diría que no es posible hacerlo en menos de O (n) ya que no está ordenado y tienes que escanear la entrada como mínimo.

Si necesita hacer muchas búsquedas posteriores, entonces una BST podría ayudar.

Respondido el 31 de enero de 12 a las 12:01

Puedes hacerlo en los siguientes pasos

Paso 1: : Ordenar matriz

Paso 2: : Buscar índice del elemento de búsqueda

Paso 3: : Según el índice, muestra el número que se encuentra en el lado derecho e izquierdo

Avísame en caso de cualquier consulta ...

Respondido el 31 de enero de 12 a las 13:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.