Một cách để suy nghĩ về vấn đề này là sử dụng thực tế là một inorder đi bộ của cây sẽ sản xuất tất cả các yếu tố theo thứ tự sắp xếp. Nếu bạn có thể phát hiện sai lệch từ thứ tự được sắp xếp trong khi đi bộ này, bạn có thể tìm cách xác định hai phần tử sai vị trí.
Hãy xem cách thực hiện điều này cho một mảng được sắp xếp đơn giản trước tiên, sau đó sẽ sử dụng thuật toán của chúng tôi để tạo thứ gì đó hoạt động trên cây. Trực giác, nếu chúng ta bắt đầu với một mảng được sắp xếp và sau đó hoán đổi hai phần tử (không bằng nhau!), Chúng ta sẽ kết thúc với một số phần tử trong mảng bị mất vị trí. Ví dụ, với các mảng
1 2 3 4 5
Nếu chúng ta trao đổi 2 và 4, chúng ta kết thúc với mảng này:
1 4 3 2 5
Làm thế nào chúng ta sẽ phát hiện rằng 2 và 4 đã được hoán đổi ở đây? Vâng, vì 4 là lớn hơn trong hai phần tử và được hoán đổi xuống, nên lớn hơn cả hai phần tử xung quanh nó. Tương tự như vậy, bởi vì 2 đã được hoán đổi, nó phải nhỏ hơn cả hai yếu tố xung quanh nó. Từ đó, chúng ta có thể kết luận rằng 2 và 4 được đổi chỗ.
Tuy nhiên, điều này không phải lúc nào cũng hoạt động chính xác. Ví dụ: giả sử chúng tôi trao đổi 1 và 4:
4 2 3 1 5
Ở đây, cả 2 và 1 đều nhỏ hơn các thành phần lân cận và cả 4 và 3 đều lớn hơn các phần tử lân cận.Từ điều này chúng ta có thể nói rằng hai trong số bốn cách này đã được đổi chỗ, nhưng không rõ chúng ta nên trao đổi cái gì. Tuy nhiên, nếu chúng ta lấy giá trị lớn nhất và nhỏ nhất của các giá trị này (lần lượt là 1 và 4), chúng ta sẽ nhận được cặp đã được hoán đổi.
Tổng quát hơn, để tìm các yếu tố đã được hoán đổi trong trình tự, bạn muốn tìm
- tối đa địa phương lớn nhất trong mảng.
- Tối thiểu địa phương nhỏ nhất trong mảng.
Hai yếu tố này không đúng chỗ và cần được hoán đổi.
Bây giờ, hãy suy nghĩ về cách áp dụng điều này cho cây. Vì một bước đi sắp xếp của cây sẽ tạo ra trình tự sắp xếp với hai phần tử ra khỏi trật tự, một lựa chọn là đi bộ cây, ghi lại chuỗi thứ tự các phần tử chúng ta đã tìm thấy, sau đó sử dụng thuật toán trên. Ví dụ, hãy xem xét BST ban đầu của bạn:
20
/ \
15 30
/ \ / \
10 17 25 33
/| /\ /\ | \
9 16 12 18 22 26 31 34
Nếu chúng ta linearize này vào một mảng, chúng tôi nhận
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
ý rằng 16 là lớn hơn yếu tố xung quanh nó và rằng 12 là ít hơn các sản phẩm. Điều này ngay lập tức cho chúng ta biết rằng 12 và 16 đã được đổi chỗ. Một thuật toán đơn giản để giải quyết vấn đề này, do đó, sẽ làm một bước đi trật tự của cây để tuyến tính hóa nó thành một chuỗi như là vector
hoặc deque
, sau đó quét chuỗi đó để tìm tối đa địa phương lớn nhất và nhỏ nhất tối thiểu địa phương. Điều này sẽ chạy trong thời gian O (n), sử dụng không gian O (n). Thuật toán hiệu quả hơn nhưng không gian hiệu quả hơn sẽ chỉ theo dõi ba nút tại một thời điểm - nút hiện tại, nút tiền nhiệm của nó và người kế nhiệm - làm giảm mức sử dụng bộ nhớ thành O (1).
Hy vọng điều này sẽ hữu ích!
getmax và getmin làm gì? nó không rõ ràng với tôi những gì bạn đang yêu cầu. – phoxis
@phoxis: getMax và getMin tìm các phần tử tối đa và tối trong cây con trái và phải của gốc chính. – Cipher
Bạn có nghĩa là: bạn đã có một BST, hai nút đã được đổi chỗ "bất hợp pháp" (vì vậy cấu trúc của bạn không phải là BST nữa) và bạn muốn biết những cái nào? –