代码链接:
https://leetcode.com/problems/recover-binary-search-tree/description/
思路:
找到两个需要交换的节点(first,second),将它们的值交换即可。
根据二叉搜索树的特性,中序遍历序列是一个递增序列(a1<a2<a3<...<an)。
(1)若ai>a(i+1)则ai即为第一个需要交换的节点;
(2)若j>=i && aj>a(j+1)则a(j+1)是第二个需要交换的节点;
(3)交换(ai,a(j+1))。
假设一个有问题的二叉搜索树的中序遍历序列为:
5,2,3,4,1
则5是第一个节点,因为5>2,4>1所以5是第一个,1是第二个需要交换的节点。
方法1:
使用递归的方式:
void InorderTraverse(root){
InorderTraverse(root->left);
do_something(root);
InorderTraverse(root->right);
}
由于在递归调用过程中使用了栈,这种方法的空间复杂度是O(n)。
方法2:
使用Morris遍历的方式。
while(root){
if(root->left){
tmp=root->left;
while(tmp->right!=NULL && tmp->right!=root)
tmp=tmp->right;
if(tmp->right){
tmp->right=NULL;
do_something(root);
root=root->right;
}
else{
tmp->right=root;
root=root->left;
}
}
else{
do_something(root);
root=root->right;
}
}
把do_something(root);替换为实际代码即可。
/**
* 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 recoverTree(TreeNode* root) {
TreeNode *pt=NULL;
TreeNode *first=NULL,*second=NULL,*prev=new TreeNode(INT_MIN);
while(root){
if(root->left){
pt=root->left;
while(pt->right && pt->right!=root)
pt=pt->right;
if(pt->right){
pt->right=NULL;
if(first==NULL && prev->val > root->val)
first=prev;
if(first && prev->val > root->val)
second=root;
prev=root;
root=root->right;
}
else{
pt->right=root;
root=root->left;
}
}
else{
if(first==NULL && prev->val > root->val)
first=prev;
if(first && prev->val > root->val)
second=root;
prev=root;
root=root->right;
}
}
if(first){
int tmp=first->val;
first->val=second->val;
second->val=tmp;
}
}
};