Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Example:
Input: [1,3,null,null,2]
1
/
3
\
2
Output: [3,1,null,null,2]
3
/
1
\
2
解析
直接交换两位置的节点值,重点在找到节点位置。
最简单的就是直接中序遍历整棵树,保存节点和节点值,对节点值进行排序,将排好序的节点值赋给节点。空间复杂度为O(n)。
解法1:空间复杂度O(n)
利用三个指针,分别为pre指向当前节点(即根节点)的前驱节点,first指针指向第一个交换的地方,second指针指向第二个交换的地方,利用中序遍历得到两个指针,并交换节点值。
例子:
假设中序遍历为163452,需要交换的为2和6,首先pre=1,root从1往后移:
当root=3时,pre=6,此时pre大于root,违反中序遍历的顺序,由于first初始为NULL,则令first=pre=6为第一个交换点,second=root(如果后续没有顺序错误这里second就是第二个交换点);
当root=2时,pre=5,违反同上,此时first不为NULL,second=root=2,中序遍历结束;
交换first=6和second=2的节点值。
class Solution {
public:
TreeNode* pre, *first, *second;
void recoverTree(TreeNode* root) {
pre = first = second = NULL;
inorder(root);
if(first && second)
swap(first->val, second->val);
}
void inorder(TreeNode* root){
if(!root) return;
inorder(root->left);
if(!pre) pre = root;
else{
if(pre->val > root->val){
if(!first) first = pre;
second = root;
}
pre = root;
}
inorder(root->right);
}
};
解法2:空间复杂度O(1)
利用Morris遍历来实现中序遍历的O(1)空间复杂度,Morris遍历算法具体步骤查看Binary Tree Inorder Traversal。
在解法1和Morris遍历的基础上增加一个指针记录上一个访问的节点。即总共有cur, pre, first, second, precur五个指针。
class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *cur, *pre, *first, *second, *parent;
first = second = parent = NULL;
cur = root;
while(cur){
if(!cur->left){
if(parent && parent->val > cur->val){
if(!first) first = parent;
second = cur;
}
parent = cur;
cur = cur->right;
}
else{
pre = cur->left;
while(pre->right && pre->right != cur)
pre = pre->right;
if(!pre->right){
pre->right = cur;
cur = cur->left;
}
else{
if(parent->val > cur->val){
if(!first) first = parent;
second = cur;
}
parent = cur;
pre->right = NULL;
cur = cur->right;
}
}
}
if(first && second) swap(first->val, second->val);
}
};
参考
http://www.cnblogs.com/grandyang/p/4298069.html
Morris遍历,Binary Tree Inorder Traversal