題目
二叉搜索樹中的兩個節點被錯誤地交換。
請在不改變其結構的情況下,恢復這棵樹。
示例1
示例2
算法實現:
class Solution {
public:
// s1 存小索引那個結點,s2存大索引那個結點,pre存前驅結點
TreeNode *s1 = NULL, *s2 = NULL, *pre = NULL;
void recoverTree(TreeNode* root) {
TreeNode* cur = root; // 遊標
while(cur != NULL){
if(cur->left != NULL){ // 進入左子樹
// 找到cur的前驅結點,分兩種情況
// 1、cur的左子結點沒有右子結點,那cur的左子結點就是前驅
// 2、cur的左子結點有右子結點,就一路向右下,走到底就是cur的前驅
TreeNode* predecessor = cur->left;
while(predecessor->right != NULL && predecessor->right != cur){
predecessor = predecessor->right;
}
// 前驅還沒有指向自己,說明左邊還沒有遍歷,將前驅的右指針指向自己,後進入前驅
if(predecessor->right == NULL){
predecessor->right = cur;
cur = cur->left;
}else{
// 前驅已經指向自己了,直接比較是否有逆序對,然後進入右子樹
if(pre != NULL && cur->val < pre->val){
if(s1 == NULL) s1 = pre;
s2 = cur;
}
pre = cur;
predecessor->right = NULL;
cur = cur->right;
}
}else{ // 左子樹爲空時,檢查是否有逆序對,然後進入右子樹
if(pre != NULL && cur->val < pre->val){
if(s1 == NULL) s1 = pre;
s2 = cur;
}
pre = cur;
cur = cur->right;
}
}
// 進行交換
int t = s1->val;
s1->val = s2->val;
s2->val = t;
return;
}
};