Dada una std::vector
de elementos distintos clasifican en orden ascendente, quiero desarrollar un algoritmo que determina si hay dos elementos de la colección cuya suma es un cierto valor, sum
.
He intentado dos enfoques diferentes con sus respectivas compensaciones:
Puedo escanear todo el vector y, para cada elemento del vector, aplicar la búsqueda binaria (
std::lower_bound
) en el vector para buscar un elemento correspondiente a la diferencia entresum
y el elemento actual. Esta es una solución de tiempo O (n log n) que no requiere espacio adicional.Puedo atravesar todo el vector y llenar un
std::unordered_set
. Luego, escaneo el vector y, para cada elemento, buscostd::unordered_set
la diferencia entresum
y el elemento actual. Dado que la búsqueda en una tabla hash se ejecuta en tiempo constante en promedio, esta solución se ejecuta en tiempo lineal. Sin embargo, esta solución requiere espacio lineal adicional debido a lastd::unordered_set
estructura de datos.
Sin embargo, estoy buscando una solución que se ejecute en tiempo lineal y no requiera espacio lineal adicional. ¿Algunas ideas? Parece que me veo obligado a cambiar la velocidad por el espacio.
bueno, dado que ya tenemos una matriz ordenada, podemos hacerlo con un enfoque de dos punteros, primero mantenemos un puntero izquierdo al comienzo de la matriz y un puntero derecho al final de la matriz, luego en cada iteración verificamos si la suma del valor de el índice del puntero izquierdo y el valor del índice del puntero derecho son iguales o no, en caso afirmativo, regrese de aquí, de lo contrario, tenemos que decidir cómo reducir el límite, es decir, aumentar el puntero izquierdo o disminuir el puntero derecho, por lo que comparamos la suma temporal con suma dada y si esta suma temporal es mayor que la suma dada, entonces decidimos reducir el puntero derecho, si aumentamos el puntero izquierdo, la suma temporal permanecerá igual o solo aumentará pero nunca menor, por lo que decidimos reducir el puntero derecho para que la suma temporal disminuye y llegamos cerca de nuestra suma dada, de manera similar si la suma temporal es menor que la suma dada,así que no tiene sentido reducir el puntero derecho como suma temporal, ya sea suma o disminución más, pero nunca aumentará, así que aumentamos nuestro puntero izquierdo para que nuestra suma temporal aumente y lleguemos a la suma dada, y hacemos el mismo proceso una y otra vez a menos que obtener la suma igual o el valor del índice del puntero izquierdo se vuelve mayor que el índice del puntero derecho derecho o viceversa a continuación se encuentra el código para la demostración, avíseme si algo no está claroavíseme si algo no está claroavíseme si algo no está claro
fuente