LeetCode99—Recover Binary Search Tree
恢复排序二叉树
原题
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?
confused what “{1,#,2,3}” means? > read more on how binary tree is serialized on OJ.Subscribe to see which companies asked this question
排序二叉树当中出现了两个元素的交换,这导致排序二叉树的性质不再,请恢复他原来的样子,且不能改变其结构。
分析
主要是不能改变结构这点让人头疼,一直没有找到合适的办法,看了网上的思路:
由于排序二叉树的中序遍历是递增序列,假如是1234567 ,那么假设当相邻两个访问的节点发生交换,比如23交换,则中序遍历序列变成了,1324567,此时序列中有1一个逆序对,我们直接交换这个逆序对即可。假设不是相邻的两个节点发生交换,即假设26交换,则中序遍历序列变成了1634527,出现了63和52两个逆序对,这个时候我们要将第一个逆序对的第一个元素和第二个逆序对的第二个元素交换。基于上述说明,这题可以这样,首先中序遍历,维护一个变量记录前一个访问的节点值,当出现第一次逆序时,我们把前一个访问节点和当前节点全部放入vector中,遍历结束我们对vector进行判断,有如下几种情况:
1. 为空,没有逆序对,不做任何操作
2. 不为空,判断容器大小:
a.vec.size()==2
,直接交换两值即可。
b.vec.size()==4
,交换vec[0]和vec[3]
第一个逆序的第一个数和第二个逆序的第二个数。
c.这是写代码的时候发生的一个意外没有考虑,也就是当被交换的数隔一个节点时:例如当原本的访问顺序为1234567,3和5交换则出现访问序列1254367,这里确实有两个逆序对,54和43,但是他们公用了一个元素4,所以在最后判断的时候加上vec.size()==3
这个条件。
代码
class Solution {
private:
void helper(TreeNode*root, TreeNode*&pre, vector<TreeNode*>&res)
{
if (root == NULL)
return;
helper(root->left, pre, res);
if (pre != NULL&&pre->val > root->val)
{
res.push_back(pre);
res.push_back(root);
}
pre = root;
helper(root->right, pre, res);
}
public:
void recoverTree(TreeNode* root) {
vector<TreeNode*>res;
TreeNode*pre = NULL;
helper(root, pre, res);
if (res.size() > 0)
{
if(res.size()==2)
swap(res[0]->val, res[1]->val);
if(res.size()==3)
swap(res[0]->val,res[2]->val);
if(res.size()==4)
swap(res[0]->val,res[3]->val);
}
}
};