Me encontré con una pregunta de algoritmo interesante en una entrevista. Di mi respuesta, pero no estoy seguro de si hay alguna idea mejor. Así que doy la bienvenida a todos para que escriban algo sobre sus ideas.Encontrar el valor mediano de un conjunto creciente
Tiene un juego vacío. Ahora los elementos se ponen en el conjunto uno por uno. Suponemos que todos los elementos son enteros y son distintos (de acuerdo con la definición de conjunto, no consideramos dos elementos con el mismo valor).
Cada vez que se agrega un nuevo elemento al conjunto, se solicita el valor mediano del conjunto. El valor mediano se define igual que en matemáticas: el elemento medio en una lista ordenada. Aquí, especialmente, cuando el tamaño del conjunto es par, asumiendo el tamaño del conjunto = 2 * x, el elemento mediano es el elemento x-ésimo del conjunto.
Un ejemplo: Comience con un conjunto vacío, cuando se añade 12, la mediana es 12, cuando se añade 7, la mediana es 7, cuando 8 se añade, la mediana es 8, cuando 11 se añade, la mediana es 8, cuando se añade 5, la mediana es 8, cuando se añade 16, la mediana es 8, ...
en cuenta que, primero, se añaden elementos de ajustar de uno en uno y segundo, no sabemos los elementos que van a agregarse.
Mi respuesta.
Dado que se trata de encontrar una mediana, es necesario ordenarla. La solución más fácil es usar una matriz normal y mantener ordenada la matriz. Cuando aparece un elemento nuevo, use la búsqueda binaria para encontrar la posición del elemento (log_n) y agregue el elemento a la matriz. Como es una matriz normal, se necesita cambiar el resto de la matriz, cuya complejidad de tiempo es n. Cuando se inserta el elemento, podemos obtener inmediatamente la mediana, utilizando el tiempo de la instancia.
La complejidad del tiempo es peor: log_n + n + 1.
Otra solución es utilizar la lista de enlaces. La razón para usar la lista de enlaces es eliminar la necesidad de cambiar la matriz. Pero encontrar la ubicación del nuevo elemento requiere una búsqueda lineal. Agregar el elemento toma tiempo instantáneo y luego tenemos que encontrar la mediana pasando por la mitad de la matriz, que siempre lleva n/2 veces.
La PEOR complejidad del tiempo es: n + 1 + n/2.
La tercera solución es utilizar un árbol de búsqueda binario. Usando un árbol, evitamos cambiar la matriz. Pero usar el árbol de búsqueda binaria para encontrar la mediana no es muy atractivo. Por lo tanto, cambio el árbol de búsqueda binaria de forma que siempre sea el caso de que el subárbol izquierdo y el subárbol derecho estén equilibrados. Esto significa que, en cualquier momento, el subárbol izquierdo y el subárbol derecho tienen el mismo número de nodos o el subárbol derecho tiene un nodo más que en el subárbol izquierdo. En otras palabras, se garantiza que en cualquier momento, el elemento raíz sea la mediana. Por supuesto, esto requiere cambios en la forma en que se construye el árbol. El detalle técnico es similar a la rotación de un árbol rojo-negro.
Si el árbol se mantiene correctamente, se garantiza que la PEOR complejidad del tiempo sea O (n).
De modo que los tres algoritmos son todos lineales al tamaño del conjunto. Si no existe un algoritmo sublineal, los tres algoritmos pueden considerarse las soluciones óptimas. Como no difieren mucho entre sí, la mejor es la más fácil de implementar, que es la segunda, mediante la lista de enlaces.
Entonces, lo que realmente me pregunto es si habrá un algoritmo sublineal para este problema y, de ser así, cómo será. Alguna idea chicos?
Steve.
http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree No estoy seguro de si es útil encontrar la mediana o su complejidad es inferior a O (n) – Aziz
No está claro exactamente cuál es la pregunta.¿Desea la complejidad para insertar en el conjunto + encontrar la mediana, o simplemente encontrar la mediana dentro de varias implementaciones de un conjunto? –
Su primer algoritmo es simplemente ordenar por inserción. Si puede implementar la ordenación por inserción en O (log (n) + n + 1) (que es solo O (n)), le animo a que publique su código ... –