LeetCode 99 - Recover Binary Search Tree
題目
題目連結:https://leetcode.com/problems/recover-binary-search-tree/
給定一個二元搜尋樹,恰好有兩個點被交換了。
復原出原本的二元搜尋樹。
範例說明
Example 1:
1 | Input: root = [1,3,null,null,2] |
Example 2:
1 | Input: root = [3,1,4,null,null,2] |
想法
二元搜尋樹的其中一個重要的性質就是其中序走訪(Inorder Traversal)恰好就是排序好的序列。
知道這個性質後,對這個錯誤的搜尋樹使用中序走訪,可以得到一個序列,因為兩個點恰好被交換,因此得到的序列中應該是排序好的,但是恰好有兩個數字被交換了。
題目因此可以變成『給一個排序好的序列,裡面恰好有兩個數字被交換,找出原本的序列』。
考慮一個 1 ~ 9 排序好的序列,有兩種交換數字的可能性:
-
交換的數字是相鄰的
Example:交換 3, 4。1
21 2 3 4 5 6 7 8 9
1 2 4 3 5 6 7 8 9可以發現,相鄰兩數交換後會產生一個相鄰的逆序數對{(4, 3)},復原這個逆序數對即可。
-
交換的數字是不相鄰的
Example: 交換 3, 7。1
21 2 3 4 5 6 7 8 9
1 2 7 4 5 6 3 8 9可以發現,不相鄰兩數交換後會產生兩個相鄰的逆序數對 {(7, 4), (6, 3)},則交換第一個逆序數對中的前面的數,以及第二組逆序數對中後面的數即可。
統整來說,我們可以在中序走訪中尋找相鄰的逆序數對,如果有一組的話,則交換逆序數對的兩數;如果有兩組的話,則交換第一組逆序數對前面的數以及第二組逆序數對後面的數。
實作細節
利用 lastNode
紀錄上一個點,若 lastNode == nullptr
代表當前是根節點,否則當 lastNode->val > root->val
時,則逆序數對產生。
利用 target
紀錄第一組逆序數對中的第一個數字,利用 candidate
紀錄要與 target
交換的另一個數。
因此,在遇到第一組逆序數對時,先假設只有一組,也就是 candidate
應該等於第一組逆序數對的第二個數字,也就是當前的節點 root
的數字,並繼續走訪。當遇到第二組逆序數對時,可以知道 candidate
應該要換成第二組逆序數對後面的數,也就是當前的節點 root
。
最後遍歷完成後交換 target
, candidate
上的值即可。
程式碼
1 | /** |