Suponiendo que haya al menos un par de elementos que satisfagan las condiciones y que no se desborde la multiplicación de dos elementos, esto puede hacerse en el Theta(n-k)tiempo y el Theta(1)espacio en el peor y el mejor de los casos, con algo como esto:
auto back_max = a[0];
auto back_min = a[0];
auto best = a[0]*a[k+1];
for(std::size_t i=1; i<n-(k+1); ++i) {
back_max = std::max(back_max, a[i]);
back_min = std::min(back_min, a[i]);
best = std::min(best, std::min(a[i+k+1]*back_max, a[i+k+1]*back_min));
}
return best;
Esto es óptimo en términos de la complejidad asintótica del peor de los casos, tanto para el tiempo como para el espacio, porque el producto óptimo puede estar a[0]con cualquiera de los n-(k+1)elementos en la distancia, al menos k+1, por lo n-(k+1)que cualquier algoritmo que resuelva el problema debe leer al menos los enteros.
La idea detrás del algoritmo es la siguiente:
El producto óptimo utiliza dos elementos de a, suponga que estos son a[r]y a[s]. Sin pérdida de generalidad podemos suponer que s > rdado que el producto es conmutativo.
Debido a la restricción, abs(s-r) > kesto implica que s >= k+1. Ahora spodría ser cada uno de los índices que satisfagan esta condición, por lo que iteramos sobre estos índices. Esa es la iteración ien el código que se muestra, pero se cambia por k+1conveniencia (realmente no importa). Para cada iteración, necesitamos encontrar el producto óptimo que incluya el i+k+1mayor índice y compararlo con la mejor estimación anterior.
Los índices posibles para emparejar i+k+1son todos índices menores o iguales idebido al requisito de distancia. Tendríamos que repetir todo esto también, pero eso es innecesario porque el mínimo de a[i+k+1]*a[j]over jen fijo ies igual a min(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))debido a la monotonicidad del producto (tomando el mínimo con respecto al mínimo y al máximo sobre a[j]cuentas para los dos posibles signos de, a[i+k+1]o equivalentemente, las dos posibles direcciones de monotonicidad.)
Dado que el conjunto de a[j]valores sobre el que optimizamos aquí es justo {a[0], ..., a[i]}, que simplemente crece por un elemento ( a[i]) en cada iteración de i, simplemente podemos realizar un seguimiento de max(a[j])y min(a[j])con variables individuales actualizándolas si a[i]es mayor o menor que los valores óptimos anteriores. Esto se hace con back_maxy back_minen el ejemplo de código.
El primer paso de la iteración ( i=0) se omite en el bucle y, en su lugar, se realiza como inicialización de las variables.
std::vector? @Scheff: la clasificación destruiría las relaciones originales de "distancia".