天天看点

[leetcode] 99.Recover Binary Search Tree

题目:

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?

confused what “{1,#,2,3}” means? > read more on how binary tree is serialized on OJ.

题意:

一棵二叉树中有两个节点互相交换了位置,找出这两个节点。

思路:

1.我们知道二叉搜索树的中序遍历的结果是元素递增的排列,如果某两个元素交换了位置,那么就不会保证递增性。比方说原来下标为i,j的两个元素互相交换了位置即A[i]与A[j]互相交换了位置,那么现在A[i+1] < A[i], A[j] <A[j-1],我们可以找到比前面元素小的两个元素即A[i+1],A[j]也即找到了A[i],A[j]。采用递归的方法进行遍历,中间过程,只比较上一个元素。

以上。代码如下:

class Solution {
public:
    void recoverTree(TreeNode* root) {
        if (root == NULL)return;
        TreeNode* first = NULL, *second = NULL;
        TreeNode* last = new TreeNode(INT_MIN);
        recoverTree(root, first, second, last);
        if (first == NULL)return;
        swap(first->val, second->val);
    }
    void recoverTree(TreeNode* root, TreeNode* &first, TreeNode* &second, TreeNode*& last) {
        if (root == NULL)return;
        recoverTree(root->left, first, second, last);
        if (root->val < last->val) {
            if (first == NULL) {
                first = last;
                second = root;
            }
            else {
                second = root;
                return;
            }
        }
        last = root;
        recoverTree(root->right, first, second, last);
    }
};
           

2.之前使用递归的方式进行遍历,平均需要额外的空间复杂度是O(lgn)(递归的深度,最差可能是O(n))。采用Morris algorithm进行中序遍历,可以参考http://blog.csdn.net/u014673347/article/details/47974555

代码如下:

class Solution {
public:
    void recoverTree(TreeNode* root) {
        if (root == NULL)return;
        TreeNode* first = NULL, *second = NULL;
        TreeNode* last = new TreeNode(INT_MIN);
        TreeNode* prev = NULL, *curr = root;
        while (curr != NULL) {
            if (curr->left == NULL) {
                if (last->val > curr->val) {
                    if (first == NULL) {
                        first = last;
                        second = curr;
                    }
                    else{
                        second = curr;
                    }
                }
                last = curr;
                curr = curr->right;
            }
            else {
                prev = curr->left;
                while (prev->right != NULL && prev->right != curr)
                    prev = prev->right;
                if (prev->right == NULL) {
                    prev->right = curr;
                    curr = curr->left;
                }
                else {
                    if (last->val > curr->val) {
                        if (first == NULL) {
                            first = last;
                            second = curr;
                        }
                        else{
                            second = curr;
                        }
                    }
                    last = curr;
                    prev->right = NULL;
                    curr = curr->right;
                }
            }
        }
        if (first == NULL)return;
        swap(first->val, second->val);
    }
};