BST 中兩個節點被錯誤交換,恢復樹結構不變、值正確。要求 O(1) 空間(Morris 遍歷)或 O(h) 空間(遞歸/棧)。
正確 BST 中序遍歷嚴格遞增。交換兩節點後,中序序列會有一處或兩處逆序:
... 3 2 4 ... → 一處逆序 (3,2)。... 5 ... 2 ... → 兩處逆序 (5,2) 和 (4,5?) 實際為 (5,2) 和 (3,4?) 需仔細分析。統一規律:第一個逆序的前一個節點 和 最後一個逆序的後一個節點 即為兩個錯誤節點。
void recoverTree(TreeNode* root) {
TreeNode *pre = nullptr, *n1 = nullptr, *n2 = nullptr, *cur = root;
while (cur) {
if (!cur->left) {
// 訪問 cur
if (pre && pre->val > cur->val) {
n1 = cur; if (!n2) n2 = pre;
}
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; // 恢復
// 訪問 cur
if (pre && pre->val > cur->val) {
n1 = cur; if (!n2) n2 = pre;
}
pre = cur;
cur = cur->right;
}
}
}
swap(n1->val, n2->val);
}
n1 為最後一次逆序的 cur,n2 為第一次逆序的 pre。swap(val)。