99. 恢复二叉搜索树
题目描述
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
示例 2:
输入: [3,1,4,null,null,2]
3
/ \66
1 4
/
2
输出: [2,1,4,null,null,3]
2
/ \
1 4
/
3
进阶:
使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
思路
根据实际例子总结规律
按照中序遍历的方式,将这颗问题二叉搜索树的节点值排列起来,从左往右,我们遇到的第一个问题节点,是从后面被错误放到了前面,因为是从后面错放到了前面,所以针对第一个错误节点,它的异常情况是它的值大于它的下一个节点;而第二个问题节点是从前面被错误放到后面的,所以它的异常情况是它的值小于前一个值。
总结起来:
第一个错误节点,pre>cur(pre为错误节点)
第二个错误节点,pre>cur(cur为错误节点)
需要注意的是,相邻节点互换时,只会出现一次pre>cur的异常情况,而不相邻的节点互换时,会出现两次pre>cur的异常情况,设计程序时需要注意到这一点。
代码实现1
class Solution {
public:
void recoverTree(TreeNode *root) {
//如果这个二叉搜索树是空树或者单节点树,则不需要
//进行修正操作
if(!root || (!root->left && !root->right))
return;
TreeNode *p1 = nullptr;
TreeNode *p2 = nullptr;
TreeNode *pre = nullptr;
recoverTreeCore(root,pre,p1,p2);
if(p1 && p2)
{
int temp = p1->val;
p1->val = p2->val;
p2->val = temp;
}
}
void recoverTreeCore(TreeNode *root,TreeNode* &pre,TreeNode* &first,TreeNode * &second)
{
if(root == nullptr)
return;
//由于前面的递归终止条件,如果没有左节点,会直接返回
recoverTreeCore(root->left,pre,first,second);
//针对当前节点做的操作
if(pre!=nullptr && pre->val > root->val)//出现异常时发生的状态情形
{ //这个条件说明我们遇到的是第一个问题节点
if(first == nullptr)
first = pre;
second = root;
}
pre = root;
recoverTreeCore(root->right,pre,first,second);
}
};
代码实现2
class Solution {
public:
void recoverTree(TreeNode *root) {
//如果这个二叉搜索树是空树或者单节点树,则不需要
//进行修正操作
if(!root || (!root->left && !root->right))
return;
TreeNode *p1 = nullptr;
TreeNode *p2 = nullptr;
TreeNode *pre = nullptr;
//由cnt我们可以得知总共发生异常的次数,及交换的是相邻还是不相邻的元素这个信息
int cnt = 0;
recoverTreeCore(root,pre,p1,p2,cnt);
if(p1!=nullptr && p2!=nullptr)
{
int temp = p1->val;
p1->val = p2->val;
p2->val = temp;
}
}
//查找两个满足条件的结点,成功找到了要及时终止查找的进行,返回返回
//一个布尔类型标识是否查找成功
void recoverTreeCore(TreeNode *root,TreeNode* &pre,TreeNode* &first,TreeNode * &second,int &cnt)
{
if(root->left!=nullptr)
recoverTreeCore(root->left,pre,first,second,cnt);
if(cnt == 2)
return;
if(pre!=nullptr && pre->val > root->val)//出现异常时会发生的状况
{
cnt++;
if(first == nullptr)
first = pre;
second = root;
}
pre = root;
if(cnt == 2)
return;
else
{
if(root->right!=nullptr)
recoverTreeCore(root->right,pre,first,second,cnt);
}
}
};