Jednym ze sposobów, aby myśleć o tym problemie jest wykorzystanie faktu, że w odległości Inorder drzewa będzie produkować wszystkich elementów posortowanych. Jeśli można wykryć odchylenia od posortowanych podczas tego spaceru, można spróbować zlokalizować dwa elementy, które są w złym miejscu.
Zobaczmy, jak to zrobić za pomocą prostego posortowanej tablicy, następnie użyje nasz algorytm zbudować coś, co działa na drzewach. Intuicyjnie, jeśli zaczniemy mecz w posortowanej tablicy, a następnie zamienić dwa (nie równe!) Elementy, możemy skończyć z pewnej liczby elementów w tablicy będącej na miejscu. Na przykład, biorąc pod uwagę szereg
1 2 3 4 5
Jeśli mamy zamienić 2 i 4, to w końcu z tej tablicy:
1 4 3 2 5
W jaki sposób możemy wykryć, że 2 i 4 zostały zamienione tutaj? Cóż, od 4 jest większa z dwóch elementów i zostało zamienione w dół, powinien być większy niż oba elementy wokół niego. Podobnie, ponieważ 2 został zamieniony w górę powinna być mniejsza niż oba elementy wokół niego. Z tego możemy wywnioskować, że 2 i 4 zostały zamienione.
Jednak to nie zawsze działa poprawnie. Na przykład, załóżmy, że mamy zamienić 1 i 4:
4 2 3 1 5
Tutaj zarówno 2 i 1 są mniejsze niż ich sąsiednich elementów, a oba 4 i 3 są większe niż ich. Z tego możemy powiedzieć, że dwa z tych czterech jakoś zostały zamienione, ale nie jest jasne, które z nich powinniśmy zamienić. Jednak jeśli weźmiemy największą i najmniejszą z tych wartości (1 i 4, odpowiednio), możemy skończyć się pary, które zostało zamienione.
Mówiąc bardziej ogólnie, aby znaleźć elementy, które zostały zamienione w sekwencji, chcesz znaleźć
- Największe lokalne maksimum w tablicy.
- Najmniejsza lokalne minimum w tablicy.
Te dwa elementy są na swoim miejscu i powinny zostać zamienione.
Teraz pomyślmy o tym, jak zastosować to do drzew. Ponieważ spacer Inorder drzewa przyniesie posortowanych sekwencji z dwóch elementów w porządku, jedna z opcji byłoby iść na drzewo, nagrywanie sekwencji Inorder elementów odkryliśmy, a następnie za pomocą powyższego algorytmu. Rozważmy na przykład oryginalną BST:
20
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
Gdybyśmy zlinearyzować to do tablicy, otrzymujemy
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
Należy zauważyć, że 16 jest większa niż otaczających elementów i 12 jest mniejsza niż jego minimalna. Ten od razu mówi nam, że 12 i 16 zostały zamienione.
Prosty algorytm do rozwiązania tego problemu, dlatego byłoby zrobić spacer Inorder drzewa do linearyzacji je w kolejności jak vectorOr deque, a następnie zeskanować tę sekwencję, aby znaleźć największy lokalne maksimum i najmniejszą lokalne minimum. Byłoby to w O (n), przy użyciu O (n) przestrzeni. Trudniejsze ale algorytm oszczędzającego byłoby tylko śledzić trzy węzły w czasie - bieżącego węzła poprzednika i następcę - co zmniejsza zużycie pamięci O (1).
Mam nadzieję że to pomoże!