您的位置:首页 > 其它

[Leetcode]Recover Binary Search Tree

2014-12-01 20:26 441 查看
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?

给一棵BST,其中有两个元素被调换了位置,让我们那这棵树恢复。

根据BST的性质(上一篇博客中已提到过),把BST中序遍历一下可以得到一个升序排列的序列。那么这道题最简单的方法就是中序遍历,把遍历结果存起来,比较得出位置错误的元素,然后还原就可以,这样空间复杂度是O(n)。但是题目中要求用O(1)的空间,又应该如何解决呢?

想想上面中序遍历的过程,我们要把每个元素存下来,最后做比较。比较的过程,就是每个元素和它的前一个作比较,确保这个元素比上一个小,以此维护BST的性质。如此想来,我们遍历过程中只要保存两个元素(当前元素和上一元素)就可以维护BST的性质了。

因此,我们的解法还是用中序遍历,只不过每次要向下传递当前元素的指针作为上一元素,供下次迭代使用。

同时,我们还需要保存出错节点的指针,用来最后恢复这棵BST。这里我用了一个pair类型来保存最后要交换元素的两个指针。

到这里很多同学认为这个问题已经结束了,其实不然。这里被交换的元素还可能有两种情况:相邻元素或者不相邻元素。

如果是不相邻元素,肯定会出现两次当前节点的值比上一节点的值大的情况,两个指针分别保存就可以了。但万一是相邻元素的话,那么其实被交换的两个元素就是pre指针和当前指针的元素,那么就要保存这两个指针。所以第一次出现不符合BST性质的元素时,pair类型mistakes就要记录这两个指针。如果后面出现第二次,就再更新mistakes.second就可以了。到这里,这道题才算结束了。

PS:这道题想了好久......

class Solution {
public:
void recoverTree(TreeNode *root) {
pair<TreeNode *, TreeNode *> mistakes;
TreeNode *pre = NULL;
locateMistake(root, mistakes, pre);
if (NULL != mistakes.first && NULL != mistakes.second){
int tmp = mistakes.first->val;
mistakes.first->val = mistakes.second->val;
mistakes.second->val = tmp;
}
}
void locateMistake(TreeNode *root, pair<TreeNode *, TreeNode *> &mistakes, TreeNode *&pre){
if (NULL == root) return;
if (root->left) locateMistake(root->left, mistakes, pre);
if (pre != NULL && root->val < pre->val){
if (NULL == mistakes.first){
mistakes.first = pre;
mistakes.second = root;
}
else{
mistakes.second = root;
}
}
pre = root;
if (root->right) locateMistake(root->right, mistakes, pre);
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode BST