Necesito calcular la mediana de carrera:
Entrada: , , vector .
Salida: vector , donde es la mediana de .
(No hacer trampa con aproximaciones; me gustaría tener soluciones exactas. Los elementos son enteros grandes).
Hay un algoritmo trivial que mantiene un árbol de búsqueda de tamaño ; el tiempo total de ejecución es . (Aquí, un "árbol de búsqueda" se refiere a una estructura de datos eficiente que admite inserciones, eliminaciones y consultas medianas en tiempo logarítmico).
Sin embargo, esto me parece un poco estúpido. Aprenderemos efectivamente todas las estadísticas de pedidos dentro de todas las ventanas de tamaño , no solo las medianas. Además, esto no es demasiado atractivo en la práctica, especialmente si es grande (los árboles de búsqueda grandes tienden a ser lentos, la sobrecarga en el consumo de memoria no es trivial, la eficiencia de la memoria caché a menudo es pobre, etc.).
¿Podemos hacer algo sustancialmente mejor?
¿Hay límites inferiores (por ejemplo, ¿es el algoritmo trivial asintóticamente óptimo para el modelo de comparación)?
Editar: David Eppstein dio un buen límite inferior para el modelo de comparación. Me pregunto si, sin embargo, es posible hacer algo un poco más inteligente que el algoritmo trivial.
Por ejemplo, podríamos hacer algo en este sentido: dividir el vector de entrada en partes de tamaño ; ordenar cada parte (haciendo un seguimiento de las posiciones originales de cada elemento); y luego use el vector ordenado por partes para encontrar las medianas en ejecución de manera eficiente sin ninguna estructura de datos auxiliar. Por supuesto, esto seguiría siendo , pero en la práctica la ordenación de matrices tiende a ser mucho más rápida que el mantenimiento de los árboles de búsqueda.
Edición 2: Saeed quería ver algunas razones por las que creo que la ordenación es más rápida que las operaciones del árbol de búsqueda. Aquí hay puntos de referencia muy rápidos, para , :
- ≈ 8s: ordenando vectores con elementos cada uno
- ≈ 10s: ordenando un vector con elementos
- ≈80: inserciones y eliminaciones en una tabla hash de tamaño k
- ≈ 390s: inserciones y eliminaciones en un árbol de búsqueda equilibrado de tamaño k
La tabla hash está ahí solo para comparar; no es de uso directo en esta aplicación.
En resumen, tenemos casi un factor 50 de diferencia en el rendimiento de la ordenación frente a las operaciones de árbol de búsqueda equilibrado. Y las cosas empeoran mucho si aumentamos .
(Detalles técnicos: Datos = enteros aleatorios de 32 bits. Computadora = una computadora portátil moderna típica. El código de prueba se escribió en C ++, utilizando las rutinas de biblioteca estándar (std :: sort) y las estructuras de datos (std :: multiset, std :: unsorted_multiset). Utilicé dos compiladores C ++ diferentes (GCC y Clang), y dos implementaciones diferentes de la biblioteca estándar (libstdc ++ y libc ++). Tradicionalmente, std :: multiset se ha implementado como un árbol rojo-negro altamente optimizado).