二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 1:
输入: [1,3,null,null,2]
1
/
3
\
2
输出: [3,1,null,null,2]
3
/
1
\
2
示例 2:
输入: [3,1,4,null,null,2]
3
/ \
1 4
/
2
输出: [2,1,4,null,null,3]
2
/ \
1 4
/
3
思路:
中序遍历二叉树后得到的就是一个基本有序的数列,只要在其中找到无序的一对数交换位置即可。空间上有两个优化方法,一是不需要记录整个中序遍历的序列,只要在遍历过程中动态维护两个指针,分别指向第一个和最后一个无序的数。二是使用morris算法,通过建立临时链接可以不利用栈空间实现中序遍历,但是需要额外遍历一次左子树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void Swap(TreeNode* x,TreeNode* y){
swap(x->val,y->val);
}
void recoverTree(TreeNode* root) {
TreeNode* x=NULL;
TreeNode* y=NULL;
TreeNode* pred=NULL;
TreeNode* morrisNode=NULL;
while(root!=NULL){
if(root->left!=NULL){
morrisNode=root->left;
//向左一步,然后一直向右走到头
while(morrisNode->right!=NULL && morrisNode->right!=root){
morrisNode=morrisNode->right;
}
if(morrisNode->right==NULL){
morrisNode->right=root;
root=root->left;
}
//pred有临时链接说明root的左子树已经遍历完,断开链接,访问root,开始遍历右子树
else{
if(pred!=NULL && pred->val>root->val){
if(x==NULL) x=pred;
y=root;
}
pred=root;
morrisNode->right =NULL;
root=root->right;
}
}
else{
if(pred!=NULL && pred->val>root->val){
if(x==NULL) x=pred;
y=root;
}
pred=root;
root=root->right;
}
}
Swap(x,y);
}
};