[Leetcode]Recover Binary Search Tree

来源:互联网 发布:sql server 连接查询 编辑:程序博客网 时间:2024/06/08 18:03

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);}};



0 0