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]Recover Binary Search Tree
原文地址:http://blog.csdn.net/cr_peace/article/details/41652179