题目:
二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 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
分析:
方法(1):中序遍历二叉树(根据二叉树中序遍历升序特性),用全局变量first和second指针记录下这两个发生错误的结点,然后交换这两个节点中的关键字需要注意的是,还要用一个指针记录所遍历当前结点的前一个结点,当前第一次遇到前一个结点值大于后一个值时,就将first和second置为这两个节点,当后面还有机会遇到这样的条件时,直接更新second值(说明第一次的first和最后一次的second才是真正发送错误位置的结点,则将二者值交换即可).O(n)时间,O(1)空间
class Solution {
public:
TreeNode* first;
TreeNode* second;
TreeNode* pre;
//中序遍历。记录发生错误的两个节点
void Inorder(TreeNode* root)
{
if(root==nullptr)
return;
Inorder(root->left);
if(pre && pre->val > root->val)
{
if(first==nullptr)//第一次遇到
{
first=pre;
second=root;
}
else//不是第一次遇到(更新second)
{
second=root;
}
}
pre=root;//始终让pre在root(当前结点的前面)
Inorder(root->right);
}
void recoverTree(TreeNode* root) {
first=second=pre=nullptr;
Inorder(root);//前序遍历后,将first和second指针置位
int tmp=first->val;
first->val=second->val;
second->val=tmp;
}
};
方法(2):可以先中序遍历二叉树,将遍历关键值放在数组中,然后对其进行排序,然后用排好序的关键值取覆盖二叉树结点的值(该过程再进行一次中序遍历),这样有序的关键字就会覆盖二叉树原来的结点中的关键值。