längste nondecreasing Teilfolge in O(nlgn)
Habe ich den folgenden Algorithmus, die gut funktioniert
Habe ich versucht zu erklären, es hier für mich http://nemo.la/?p=943 und es ist hier erklärt http://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/ als auch auf stackoverflow sowie
Ich möchte es ändern zu produzieren, die längste non-monoton steigende Teilfolge
für die Folge 30 20 20 10 10 10 10
die Antwort sollte 4 sein: "10 10 10 10"
Aber das mit nlgn version des Algorithmus, es funktioniert nicht. Initialisieren s enthalten das erste element "30" und ab an das zweite element = 20. Dies ist, was passiert:
-
Den ersten Schritt: 30 nicht größer als oder gleich 20. Wir suchen das kleinste element größer als 20 sein. Der neue s wird "20"
-
Der zweite Schritt: 20 ist größer als oder gleich 20. Wir verlängern die Sequenz und s enthält jetzt "20 20"
-
Der Dritte Schritt: 10 ist nicht größer als oder gleich 20. Wir suchen das kleinste element größer als 10 "20". Der neue s wird "10 20"
und s wird nie wachsen nach, und der Algorithmus zurück 2 statt 4
int height[100];
int s[100];
int binary_search(int first, int last, int x) {
int mid;
while (first < last) {
mid = (first + last) /2;
if (height[s[mid]] == x)
return mid;
else if (height[s[mid]] >= x)
last = mid;
else
first = mid + 1;
}
return first; /* or last */
}
int longest_increasing_subsequence_nlgn(int n) {
int i, k, index;
memset(s, 0, sizeof(s));
index = 1;
s[1] = 0; /* s[i] = 0 is the index of the element that ends an increasing sequence of length i = 1 */
for (i = 1; i < n; i++) {
if (height[i] >= height[s[index]]) { /* larger element, extend the sequence */
index++; /* increase the length of my subsequence */
s[index] = i; /* the current doll ends my subsequence */
}
/* else find the smallest element in s >= a[i], basically insert a[i] in s such that s stays sorted */
else {
k = binary_search(1, index, height[i]);
if (height[s[k]] >= height[i]) { /* if truly >= greater */
s[k] = i;
}
}
}
return index;
}
- Durch nicht-monoton ansteigende Sequenz, meinst du nicht monoton Steigend? Das ist
for every i>j: x[i]>=x[j]
? - ja sorry, ich war verwirrend: es sollte "nondecreasing"
Du musst angemeldet sein, um einen Kommentar abzugeben.
Finden die am längsten nicht-streng monoton wachsende Teilfolge, änderung dieser Bedingungen:
zu:
Den vierten Schritt-für dein Beispiel-Sequenz werden sollten:
10
ist nicht weniger als10
(das kleinste element). Wir finden das größte element, das kleiner ist als oder gleich10
(das wäres[0]==10
). Klonen und erweitern Sie diese Liste durch10
. Entsorgen Sie die vorhandene Liste der Länge 2. Die neues
wird{10 10}
.Ihrem code, der fast funktioniert, bis auf ein problem in Ihrem
binary_search()
- Funktion, diese Funktion sollte den index des ersten Elements, das größer ist als das target-element(x), da Sie wollen, dass die längste nicht-Abnehmender Reihenfolge. Ändern Sie diese zu, es werde in Ordnung sein.Wenn Sie c++,
std::lower_bound()
undstd::upper_bound()
wird Ihnen helfen, loszuwerden, dieses verwirrende problem. Durch die Art und Weise, die if-Anweisung"if (height[s[k]] >= height[i])
" ist überflüssig.Nur für die längste zunehmende sub-Sequenz-Algorithmus geordnete paar (A[i], i), durch die Verwendung einer lexikographischen vergleichen.
Eine ganz andere Lösung für dieses problem ist die folgende. Machen Sie eine Kopie des Arrays und sortiert werden. Dann berechnen Sie den minimalen Wert ungleich null Unterschied zwischen zwei Elementen des Arrays (das wird der minimale Wert ungleich null Unterschied zwischen zwei benachbarte array-Elemente) und nennen es δ. Dieser Schritt braucht Zeit O(n log n).
Die wichtige Beobachtung ist, dass, wenn Sie hinzufügen 0-element 0 des ursprünglichen Arrays, δ/n, um das zweite element des ursprünglichen Arrays, 2δ/n, um das Dritte element des Arrays, etc., dann ist jede nondecreasing Sequenz in das original-array wird eine streng monoton wachsende Folge in das neue array und Umgekehrt. Deshalb verwandeln Sie das array auf diese Weise, dann führen Sie ein standard längsten steigenden Teilfolge solver, die läuft in Zeit O(n log n). Das Ergebnis dieses Prozesses ist eine O(n log n) Algorithmus für das finden der längsten nondecreasing Teilfolge.
Betrachten Sie zum Beispiel 30, 20, 20, 10, 10, 10, 10. In diesem Fall δ = 10 und n = 7, δ /n ≈ 1.42. Das neue array wird dann
Hier, die führt 14.28, 15.71, 17.14, 18.57, die Karten zurück zu 10, 10, 10, 10 in das ursprüngliche array.
Hoffe, das hilft!
Meine Java-version: