hard
二叉搜索树中的两个节点被错误地交换
请在不改变其结构的情况下,恢复这棵树
示例 1:
输入: [1,3,null,null,2]
1
/
3
\
2
输出: [3,1,null,null,2]
3
/
1
\
2
示例 2:
输入: [3,1,4,null,null,2]
3
/ \
1 4
/
2
输出: [2,1,4,null,null,3]
2
/ \
1 4
/
3
一开始我是迷茫的,看到说明里面提示了 O(n)
的空间复杂的,结合BST的性质——中序遍历严格递增,这不就出来了吗!根据提示可以有常数空间来解决这个问题,怎么实现呢?
按照前面的想法
2n
的空间list
存放节点,一个 vals
存放对应的值class Solution {
public:
void recoverTree(TreeNode* root) {
vector<TreeNode*> list;
vector<int> vals;
inorder(root, list, vals);
sort(vals.begin(), vals.end());
for (int i = 0; i < list.size(); ++i) {
list[i]->val = vals[i];
}
}
void inorder(TreeNode* root, vector<TreeNode*>& list, vector<int>& vals) {
if (!root) return;
inorder(root->left, list, vals);
list.push_back(root);
vals.push_back(root->val);
inorder(root->right, list, vals);
}
};
其实是方法一的变种
2n
的空间,这里只用了 n
class Solution {
public:
void recoverTree(TreeNode* root) {
vector<TreeNode*> list;
inorder(root, list);
int err1 = 0;
while(err1+1 < list.size() && list[err1]->val < list[err1+1]->val){
err1++;
}
int err2 = err1 + 1;
while(err2+1 < list.size() && list[err2]->val < list[err2+1]->val){
err2++;
}
if(err2 + 1 >= list.size()) err2 = err1; //遍历到最后都没有异常,故直接err1旁边交换即可
int tmp = list[err1]->val;
list[err1]->val = list[err2+1]->val;
list[err2+1]->val = tmp;
}
void inorder(TreeNode* node, vector<TreeNode*>& list){
if (!node) return;
inorder(node->left, list);
list.push_back(node);
inorder(node->right, list);
}
};
Morris遍历,参考博文:http://www.cnblogs.com/grandyang/p/4298069.html
// Now O(1) space complexity
class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *first = NULL, *second = NULL, *parent = NULL;
TreeNode *cur, *pre;
cur = root;
while (cur) {
if (!cur->left) {
if (parent && parent->val > cur->val) {
if (!first) first = parent;
second = cur;
}
parent = cur;
cur = cur->right;
} else {
pre = cur->left;
while (pre->right && pre->right != cur) pre = pre->right;
if (!pre->right) {
pre->right = cur;
cur = cur->left;
} else {
pre->right = NULL;
if (parent->val > cur->val) {
if (!first) first = parent;
second = cur;
}
parent = cur;
cur = cur->right;
}
}
}
swap(first->val, second->val);
}
};