Eine Möglichkeit, dieses Problem zu denken, ist die Tatsache zu nutzen, dass ein Inorder Fuß des Baumes wird alle Elemente in sortierter Reihenfolge erzeugen. Wenn Sie Abweichungen von der sortierten Reihenfolge während dieser Wanderung erkennen können, können Sie versuchen, die beiden Elemente zu finden, die an der falschen Stelle sind.
Mal sehen, wie das erste für eine einfache sortiertes Array zu tun, dann ist unser Algorithmus verwenden, um etwas zu bauen, die auf Bäumen funktioniert. Intuitiv, wenn wir mit einem sortierten Array beginnen und dann tauschen zwei (nicht-gleich!) Elemente, werden wir mit einem gewissen Anzahl von Elementen in der Anordnung am Ende fehl am Platz zu sein. Zum Beispiel gegeben, um die Array
1 2 3 4 5
Wenn wir 2 und 4 tauschen, enden wir mit dieser Anordnung auf:
1 4 3 2 5
Wie würden wir feststellen, dass 2 und 4 hier vertauscht wurden? Nun, da 4 der größere der beiden Elemente und wurde nach unten getauscht, sollte es größer sein als beide Elemente um ihn herum. In ähnlicher Weise wurde wegen 2 vertauscht, sollten sie kleiner sein, als beide Elemente um ihn herum. Daraus könnte man schließen, dass 2 und 4 vertauscht wurden.
Allerdings ist dies nicht immer korrekt funktionieren. Angenommen, dass wir tauschen 1 und 4:
4 2 3 1 5
Hier ist sowohl 2 und 1 sind kleiner als ihre benachbarten Elemente, und beide 4 und 3 sind größer als ihre. Daraus können wir sagen, dass zwei dieser vier irgendwie vertauscht wurden, aber es ist nicht klar, welche davon sollten wir vertauschen. Wenn wir jedoch die größte und die kleinste dieser Werte (1 bzw. 4) nehmen wir am Ende das Paar erhalten, die ausgelagert wurde.
Allgemeiner gesagt, die Elemente zu finden, die in der Reihenfolge vertauscht wurden, wollen Sie finden
- Das größte lokale Maximum in der Anordnung.
- Das kleinste lokale Minimum in der Anordnung.
Diese beiden Elemente sind fehl am Platz und sollte ausgetauscht werden.
Nun lassen Sie uns darüber nachdenken, wie diese auf Bäume anzuwenden. Da ein Inorder Fuß des Baumes wird die sortierte Folge mit den beiden Elementen aus der Ordnung zu erzeugen, würde eine Möglichkeit sein, den Baum zu gehen, die Aufzeichnung die Inorder Folge von Elementen, die wir gefunden haben, dann den obigen Algorithmus. Betrachten Sie zum Beispiel Ihre ursprüngliche BST:
20
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
Wenn wir dies in ein Array linearisieren, erhalten wir
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
Beachten Sie, dass 16 größer ist als ihre umgebenden Elemente und 12 geringer als sein. Dies sagt uns sofort, dass 12 und 16 vertauscht wurden.
Ein einfacher Algorithmus zur Lösung dieses Problems, wäre daher einen Inorder Spaziergang des Baumes zu tun , es in eine Sequenz wie ein linearisieren vectoroder deque, dann diese Sequenz zu scannen , das größte lokale Maximum und das kleinste lokale Minimum zu finden. Dies würde in O (n) Zeit ausgeführt, O (n) Raum verwendet wird . Ein heikler , aber mehr Platz sparender Algorithmus wäre nur bei einer Zeitspur von drei Knoten zu halten - den aktuellen Knoten, seinen Vorgänger und seinen Nachfolger - die die Speichernutzung zu O (1) reduziert.
Hoffe das hilft!