Een manier om na te denken over dit probleem is het feit dat een inorder lopen van de boom alle elementen in gesorteerde volgorde zal produceren gebruiken. Als u tijdens deze wandeling afwijkingen van de gesorteerde volgorde kan detecteren, kunt u proberen om de twee elementen die op de verkeerde plaats te vinden.
Laten we eens kijken hoe dit voor een eenvoudige gesorteerde array eerst doen, dan zal ons algoritme te gebruiken om iets dat werkt op bomen te bouwen. Intuïtief Als we beginnen met een gesorteerde array en wisselen twee (niet-gelijke!) Elementen, zullen eindigen met enig aantal elementen in de array zijn misplaatst. Gegeven bijvoorbeeld de matrix
1 2 3 4 5
Als we ruilen 2 en 4, komen we uit op deze array:
1 4 3 2 5
Hoe zouden we detecteren dat 2 en 4 werden hier verwisseld? Goed, aangezien 4 is de grootste van de twee elementen en is naar beneden verwisseld, moet groter zijn dan beide elementen eromheen. Evenzo, omdat 2 werd verwisseld op, moet kleiner zijn dan beide elementen eromheen. Hieruit kunnen we concluderen dat 2 en 4 werden verwisseld.
Dit betekent echter niet altijd goed werken. Stel bijvoorbeeld dat we ruilen 1 en 4:
4 2 3 1 5
Hier zijn zowel 2 en 1 kleiner zijn dan de aangrenzende elementen, en zowel 4 en 3 zijn groter dan die van hen. Hieruit kunnen we zeggen dat twee van deze vier een of andere manier werden verwisseld, maar het is niet duidelijk welke we moeten verwisselen. Echter, als we de grootste en de kleinste van deze waarden (1 en 4, respectievelijk), eindigen we krijgen van het paar, dat werd omgezet.
Meer in het algemeen, om de elementen die werden verwisseld in de volgorde te vinden, die u wilt zoeken
- De grootste lokale maximum in de array.
- De kleinste lokale minimum in de array.
Deze twee elementen misplaatst en moet worden verwisseld.
Laten we nu eens na te denken over hoe dit van toepassing op bomen. Aangezien een inorder lopen van de boom zal de gesorteerde volgorde met de twee elementen in de juiste volgorde te produceren, zou een optie zijn om de boom te lopen, het opnemen van de inorder opeenvolging van elementen die we hebben gevonden, vervolgens met behulp van het bovenstaande algoritme. Denk bijvoorbeeld aan de oorspronkelijke BST:
20
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
Als we dit te lineariseren in een array, krijgen we
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
Merk op dat 16 groter is dan de omliggende elementen en die 12 lager is dan zijn. Dit vertelt ons meteen dat 12 en 16 waren verwisseld.
Een eenvoudig algoritme voor het oplossen van dit probleem dan ook, zou zijn om te doen een inorder lopen van de boom om het te lineariseren in een reeks als een vectorof deque, dan aan deze reeks scannen naar de grootste lokale maximum en de kleinste lokaal minimum vinden. Dit zou zijn bij O (n) tijdstip en O (n) space. Een lastiger maar ruimtebesparende algoritme is om enige nummer drie knooppunten houden tegelijk - de huidige knoop, zijn voorganger en de opvolger - die het geheugengebruik te verminderen O (1).
Ik hoop dat dit helpt!