Ein Hinweis zur Methodik
Ich habe ein wenig über dieses Problem nachgedacht und bin zu einer Lösung gekommen. Als ich die Antwort von Saeed Amiri las , stellte ich fest, dass ich eine spezielle Version des Standardalgorithmus für die Suche nach der längsten Teilsequenz für eine Sequenz der Länge 3 gefunden hatte ist ein interessantes Beispiel für die Problemlösung.
Die Zwei-Elemente-Version
i<jA[i]<A[j]
A∀i<j,A[i]≥A[j]∀i,A[i]≥A[i+1]iA[i]<A[i+1]
Dieser Fall ist sehr einfach; Wir werden versuchen, es zu verallgemeinern. Es zeigt sich, dass das angegebene Problem nicht lösbar ist: Die angeforderten Indizes existieren nicht immer. Wir werden daher eher darum bitten, dass der Algorithmus entweder gültige Indizes zurückgibt, wenn sie existieren, oder korrekt behauptet, dass keine solchen Indizes existieren.
Den Algorithmus finden
A(A[i1],…,A[im])i1<⋯<imA(A[i],A[i+1],…,A[i+m−1])
Wir haben gerade gesehen, dass die angeforderten Indizes nicht immer existieren. Unsere Strategie besteht darin, zu untersuchen, wann die Indizes nicht existieren. Wir werden dies tun, indem wir annehmen, dass wir versuchen, die Indizes zu finden und zu sehen, wie unsere Suche schief gehen könnte. Dann liefern die Fälle, in denen die Suche nicht schief geht, einen Algorithmus, um die Indizes zu finden.
j=i+1k=j+1A[i]<A[i+1]<A[i+2]
A[j]<A[j+1]iA[i]<A[j]kA[j+1]<A[k]
ik
ijki
i(i,j)ki(i,j)(i,j)i′>jA[i′]<A[i]i′i(i,j)j′A[j′]<A[j](i′,j′)
Aussage des Algorithmus
In der Python-Syntax angegeben, aber beachten Sie, dass ich es nicht getestet habe.
def subsequence3(A):
"""Return the indices of a subsequence of length 3, or None if there is none."""
index1 = None; value1 = None
index2 = None; value2 = None
for i in range(0,len(A)):
if index1 == None or A[i] < value1:
index1 = i; value1 = A[i]
else if A[i] == value1: pass
else if index2 == None:
index2 = (index1, i); value2 = (value1, A[i])
else if A[i] < value2[1]:
index2[1] = i; value2[1] = A[i]
else if A[i] > value2[1]:
return (index2[0], index2[1], i)
return None
Proof-Skizze
index1
ist der Index des Minimums des Teils des Arrays, der bereits durchlaufen wurde (wenn er mehrmals auftritt, wird das erste Vorkommen beibehalten) oder None
bevor das erste Element verarbeitet wird. index2
speichert die Indizes der ansteigenden Teilsequenz der Länge 2 im bereits durchquerten Teil des Arrays, der das niedrigste größte Element hat, oder None
wenn eine solche Sequenz nicht existiert.
Wenn return (index2[0], index2[1], i)
läuft, haben wir value2[0] < value[1]
(dies ist eine Invariante von value2
) und value[1] < A[i]
(aus dem Kontext ersichtlich). Wenn die Schleife endet, ohne die frühe Rückkehr aufzurufen value1 == None
, gibt es in diesem Fall entweder keine zunehmende Teilfolge der Länge 2, geschweige denn der Länge 3, oder sie value1
enthält die zunehmende Teilfolge der Länge 2, die das niedrigste größte Element aufweist. Im letzteren Fall haben wir weiterhin die Invariante, dass keine zunehmende Folge der Länge 3 früher endet als value1
; daher würde das letzte Element einer solchen hinzugefügten value2
Teilsequenz eine zunehmende Teilsequenz der Länge 3 bilden: da wir dort auch die Invariante haben, value2
die nicht Teil einer zunehmenden Teilsequenz der Länge 3 ist, die in dem bereits durchquerten Teil des Arrays enthalten ist ist keine solche Untersequenz im gesamten Array.
Das Beweisen der vorgenannten Invarianten bleibt dem Leser als Übung überlassen.
Komplexität
O(1)O(1)O(n)
Formeller Beweis
Dem Leser als Übung überlassen.