Unter der Annahme, dass mindestens ein Elementpaar die Bedingungen erfüllt und keine Multiplikation von zwei Elementen darin überläuft, kann dies im schlimmsten und besten Fall Theta(n-k)
zeitlich und Theta(1)
räumlich erfolgen.
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;
Dies ist hinsichtlich der asymptotischen Worst-Case-Komplexität sowohl für die Zeit als auch für den Raum optimal, da das optimale Produkt mindestens a[0]
mit einem der n-(k+1)
Elemente in der Entfernung vorliegen kann k+1
, sodass mindestens n-(k+1)
ganze Zahlen von jedem Algorithmus gelesen werden müssen, der das Problem löst.
Die Idee hinter dem Algorithmus ist wie folgt:
Das optimale Produkt verwendet zwei Elemente von a
, vorausgesetzt, diese sind a[r]
und a[s]
. Ohne Verlust der Allgemeinheit können wir davon ausgehen, dass s > r
das Produkt kommutativ ist.
Aufgrund der Einschränkung abs(s-r) > k
impliziert dies, dass s >= k+1
. Nun s
könnte jeder der Indizes diese Bedingung erfüllen, also iterieren wir über diese Indizes. Dies ist die Iteration i
im angezeigten Code, die jedoch der Einfachheit halber verschoben wird k+1
(spielt keine Rolle). Für jede Iteration müssen wir das optimale Produkt mit i+k+1
dem größten Index finden und es mit der vorherigen besten Schätzung vergleichen.
Die möglichen Indizes, i+k+1
mit denen gepaart werden kann, sind i
aufgrund der Abstandsanforderung alle Indizes kleiner oder gleich . Wir müssten auch alle diese Punkte durchlaufen, aber das ist unnötig, da das Minimum von a[i+k+1]*a[j]
Over j
bei Fix i
gleich min(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))
der Monotonie des Produkts entspricht (wobei das Minimum sowohl in Bezug auf das Minimum als auch das Maximum a[j]
für die beiden möglichen berücksichtigt wird Zeichen a[i+k+1]
oder gleichwertig die beiden möglichen Richtungen der Monotonie.)
Da die Menge der a[j]
Werte, über die wir hier optimieren, gerade ist {a[0], ..., a[i]}
und die einfach um ein Element ( a[i]
) in jeder Iteration von wächst i
, können wir einfach max(a[j])
und min(a[j])
mit einzelnen Variablen verfolgen , indem wir sie aktualisieren, wenn sie a[i]
größer oder kleiner als die vorherigen optimalen Werte sind. Dies erfolgt mit back_max
und back_min
im Codebeispiel.
Der erste Schritt der Iteration ( i=0
) wird in der Schleife übersprungen und stattdessen als Initialisierung der Variablen ausgeführt.
std::vector
? @Scheff - Sortieren würde die ursprünglichen "Distanz" -Beziehungen zerstören.