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, 其实这就是个遍历的问题,因为二叉查找树中序下的严格升序性质可以很好的解决这类问题,这题之所以是hard就是因为看你是否能用常量空间解决,如同他说得一样。如果可以使用个O(n)大小的空间的话,那么直接遍历输出数据到数组或者栈,检查不满足升序的两处即可。这里得注意,交换后会出现的两种可能,如果是相邻两项交换,那么只有一处不满足升序,如果不是,那么有两处,这里需要分类判断下,锁定不同情况下的错误位置。
方法一:使用额外空间输出信息
void recoverTree(TreeNode* root) {
vector<TreeNode*> res;
helper(root, res);
TreeNode* first;
TreeNode* second;
int i;
bool once = false;
for (i = 0; i < res.size() - 1; i++) {
if (res[i]->val > res[i+1]->val && once == false) {
first = res[i];
second = res[i+1];
once = true; //如果是一处,那么直接这俩交换
}
else {// 如果是两处错误,那么应该是第一处的第一个和第二处的第二个交换
if (res[i]->val > res[i+1]->val)
second = res[i+1];
}
}
int temp;
temp = first->val;
first->val = second->val;
second->val = temp;
}
// 简单的递归将数据输出到数组
void helper(TreeNode* t, vector<TreeNode*>& res) {
if (t != NULL) {
helper(t->left, res);
res.push_back(t);
helper(t->right, res);
}
}
方法二:morris traversal
其实二叉树遍历来做这道题的话,还得是常量空间,首先想到的就是morris traversal,所以这里其实只要稍微改动就行,可以用一个lastnode来记录上一个节点,然后跟当前节点比较,如果不满足升序记录下节点即可。主要还是在morris算法本身。
void recoverTree(TreeNode* root) {
TreeNode *cur = root, *prev = NULL, *last = NULL;
TreeNode *first, *second;
bool once = false;
while (cur != NULL) {
if (last != NULL && last->val > cur->val) {
if (once == false) {
first = last;
second = cur;
once = true;
}
else second = cur;
}
if (cur->left == NULL) {
last = cur;
cur = cur->right;
}
else {
prev = cur->left;
while (prev->right != NULL && prev->right != cur)
prev = prev->right;
if (prev->right == NULL) {
prev->right = cur;
cur = cur->left;
}
else {
prev->right = NULL;
last = cur;
cur = cur->right;
}
}
}
int temp = first->val;
first->val = second->val;
second->val = temp;
}