BST 中兩個節點值被交換,恢復樹結構。要求 O(1) 空間(Morris 遍歷)或 O(h) 空間(棧/遞歸)。
BST 中序遍歷應為遞增序列。兩節點交換導致序列中出現兩處逆序(或相鄰一處)。
first(較大值)。second(較小值)。first 為前節點,second 為後節點。class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *first = nullptr, *second = nullptr, *pre = nullptr;
stack st;
TreeNode* cur = root;
while (cur || !st.empty()) {
while (cur) { st.push(cur); cur = cur->left; }
cur = st.top(); st.pop();
if (pre && pre->val > cur->val) {
if (!first) first = pre; // 第一次逆序,pre 是較大者
second = cur; // 最後一次逆序,cur 是較小者
}
pre = cur;
cur = cur->right;
}
swap(first->val, second->val);
}
};
void recoverTree(TreeNode* root) {
TreeNode *first = nullptr, *second = nullptr, *pre = nullptr;
TreeNode* cur = root;
while (cur) {
if (!cur->left) {
if (pre && pre->val > cur->val) {
if (!first) first = pre;
second = cur;
}
pre = cur;
cur = cur->right;
} else {
TreeNode* pred = cur->left;
while (pred->right && pred->right != cur) pred = pred->right;
if (!pred->right) {
pred->right = cur;
cur = cur->left;
} else {
pred->right = nullptr;
if (pre && pre->val > cur->val) {
if (!first) first = pre;
second = cur;
}
pre = cur;
cur = cur->right;
}
}
}
swap(first->val, second->val);
}
pre 指針,比較 pre->val > cur->val 檢測逆序。first 只記錄第一次逆序的 pre,second 每次逆序都更新為 cur,最終指向最後逆序的較小值。| 方法 | 時間 | 空間 |
|---|---|---|
| 遞歸/棧中序 | O(n) | O(h) |
| Morris 遍歷 | O(n) | O(1) |
此題是 BST 性質與中序遍歷結合的經典應用,Morris 遍歷展示了線索二叉樹思想,是樹算法進階必修內容。