Sie haben davon gehört, dass dies in O(n) mit einer dequeue gemacht wird.
Nun, das ist ein bekannter Algorithmus für diese Frage, um es in O(n) zu lösen.
Die Methode, die ich erzähle, ist recht einfach und hat eine Zeitkomplexität von O(n).
Ihr Beispieleingabe:
n=10, W = 3
10 3
1 -2 5 6 0 9 8 -1 2 0
Antwort = 5 6 6 9 9 9 8 2
Konzept: Dynamisches Programmieren
Algorithmus:
-
N ist die Anzahl der Elemente in einem Array und W ist die Fenstergröße. Also, Fensternummer = N-W+1
-
Teilen Sie das Array nun in Blöcke der Größe W, beginnend ab Index 1.
Hier in Blöcke der Größe 'W' = 3 unterteilen. Für Ihre Beispieleingabe:
![unterteilte Blöcke]()
-
Wir haben in Blöcke unterteilt, weil wir das Maximum auf 2 Arten berechnen werden A.) durch Traversieren von links nach rechts B.) durch Traversieren von rechts nach links. Aber wie??
-
Zunächst das Traversieren von links nach rechts. Für jedes Element ai
im Block finden wir das Maximum bis zu diesem Element ai
vom START des Blocks bis zum ENDE des Blocks. Also hier,
![LR]()
-
Zweitens das Traversieren von rechts nach links. Für jedes Element 'ai'
im Block finden wir das Maximum bis zu diesem Element 'ai'
vom ENDE des Blocks bis zum START des Blocks. Also hier,
![RL]()
-
Jetzt müssen wir das Maximum für jedes Teilarray oder Fenster der Größe 'W' finden. Also, beginnend vom Index = 1 bis zum Index = N-W+1.
max_val[index] = max(RL[index], LR[index+w-1]);
![LR + RL]()
für index=1: max_val[1] = max(RL[1],LR[3]) = max(5,5)= 5
Ähnlich, für alle Indizes i
, (i<=(n-k+1))
, wird der Wert bei RL[i]
und LR[i+w-1]
verglichen und das Maximum dieser beiden ist die Antwort für dieses Teilarray.
Also Endgültige Antwort: 5 6 6 9 9 9 8 2
Zeitkomplexität: O(n)
Implementierungscode:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LIM 100001
using namespace std;
int arr[LIM]; // Eingabearray
int LR[LIM]; // Maximum von Links nach Rechts
int RL[LIM]; // Maximum von Rechts nach Links
int max_val[LIM]; // Anzahl der Teilarrays(Fenster) ist n-k+1
int main(){
int n, w, i, k; // 'n' ist die Anzahl der Elemente im Array
// 'w' ist die Fenstergröße
cin >> n >> w;
k = n - w + 1; // 'K' ist die Anzahl der Fenster
for(i = 1; i <= n; i++)
cin >> arr[i];
for(i = 1; i <= n; i++){ // für das Maximum von Links nach Rechts
if(i % w == 1) // das bedeutet, der BEGINN eines Blocks
LR[i] = arr[i];
else
LR[i] = max(LR[i - 1], arr[i]);
}
for(i = n; i >= 1; i--){ // für das Maximum von Rechts nach Links
if(i == n) // Vielleicht ist der letzte Block nicht von Größe 'W'.
RL[i] = arr[i];
else if(i % w == 0) // das bedeutet, das ENDE eines Blocks
RL[i] = arr[i];
else
RL[i] = max(RL[i+1], arr[i]);
}
for(i = 1; i <= k; i++) // Maximum
max_val[i] = max(RL[i], LR[i + w - 1]);
for(i = 1; i <= k ; i++)
cout << max_val[i] << " ";
cout << endl;
return 0;
}
Link zum Ausführen des Codes
Ich werde versuchen zu beweisen: (von @johnchen902)
Wenn k % w != 1
(k
ist nicht der Anfang eines Blocks)
Lassen Sie k* = Der Anfang des Blocks, der k enthält
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= max( max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k*]),
max( arr[k*], arr[k* + 1], arr[k* + 2], ..., arr[k + w - 1]) )
= max( RL[k], LR[k+w-1] )
Andernfalls (k
ist der Anfang eines Blocks)
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= RL[k] = LR[k+w-1]
= max( RL[k], LR[k+w-1] )