问题描述:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
修正二叉查找树错误节点,并且不改变结构。
问题求解:
方法一:Morris中序遍历,时间复杂度O(n),空间复杂度O(1)
/**
* 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) {// Morris中序遍历,时间复杂度O(n),空间复杂度O(1)
TreeNode* cur=root;
TreeNode* pre=NULL;
pair<TreeNode*, TreeNode*> mistake;
while(cur)
{
if(cur->left==NULL)
{
findMistakeNodes(mistake, pre, cur);
pre=cur;//!!!
cur=cur->right;
}
else
{
TreeNode* tmp=cur->left;
while(tmp->right != NULL && tmp->right != cur)
{
tmp=tmp->right;
}
if(tmp->right == NULL)
{
tmp->right=cur;
//prev = cur; 不能有这句!因为cur还没有被访问
cur=cur->left;
}
else
{
findMistakeNodes(mistake, pre, cur);
tmp->right=NULL;
pre=cur;//!!!
cur=cur->right;
}
}
}
swap(mistake.first->val, mistake.second->val);
}
void findMistakeNodes(pair<TreeNode*, TreeNode*>& mistake, TreeNode* pre, TreeNode* cur)
{
if(pre != NULL && pre->val > cur->val)
{//prev->val > current->val违反了中序遍历BST的递增顺序
if(mistake.first==NULL)
{
mistake.first=pre;
}//不能用else,例如 {0,1},会导致最后 swap时second为null,
//会 Runtime Error
mistake.second=cur;
}
}
};
方法二:递归中序遍历
class Solution {
private:
TreeNode *mistake1, *mistake2;
TreeNode *pre;
public:
void recoverTree(TreeNode* root) {
mistake1=mistake2=NULL;
pre=NULL;
InOrder(root);
swap(mistake1->val, mistake2->val);
}
void InOrder(TreeNode* root)
{
if(root->left)
{//左
InOrder(root->left);
}
if(pre != NULL && pre->val>root->val)
{//中.找到两个错误的节点:当出现当前值比前一个值小的时候,就是存在不合法的节点。
if(mistake1==NULL) mistake1=pre;
mistake2=root;
}
pre=root;
if(root->right)
{//右
InOrder(root->right);
}
}
};