[LeetCode] 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?

分析:本题做的思路是找到两个需要交换的结点,把两个结点的val值进行交换即可。

以下两种方法都是LeetCode Discuss中的方法:

方法1:用递归或栈的方法对树进行中序遍历,当然这种方法不满足O(1)的空间复杂度

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void recover(TreeNode *root, TreeNode *&pre, TreeNode *&a, TreeNode *&b) {
    if (root)
    {
        recover(root->left, pre, a, b);

        if (root->val < pre->val)
        {
            if (!a) a = pre; //a should change once.
            b = root; //b could change twice.
        }
        pre = root;

        recover(root->right, pre, a, b);
    }
}
void recoverTree(TreeNode *root) {
    if (!root) return;

    TreeNode p(numeric_limits<int>::min());
    TreeNode *a, *b, *pre;
    a = b = 0;
    pre = &p;
    recover(root, pre, a, b);
    if (a && b)
    {
        swap(a->val, b->val);
    }
    return;
}
};

方法2:morris traversal的方法,这种方法借鉴线索二叉树的方法,即不用递归和栈,用改变树的关键结点的指向的方法来遍历二叉树,使用完指向信息后,再将树恢复。参见http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/

class Solution {
public:
    void recoverTree(TreeNode *root) {
        if (root == NULL) return;
        TreeNode * ptr, *pred, * current;
        TreeNode * pred1, * cur1, * pred2, * cur2;

        current = root; ptr = pred = NULL;
        pred1 = cur1 = pred2 = cur2 = NULL;

        while (current != NULL){
            if (current->left == NULL){
                pred = current;
                current = current->right;
            }else{
                ptr = current->left;
                while (ptr->right != NULL && ptr->right != current)
                    ptr = ptr->right;
                if (ptr->right == NULL){//构造线索二叉树
                    ptr->right = current;
                    current = current->left;
                }else{                  //把线索二叉树恢复成原先的二叉树
                    ptr->right = NULL;
                    pred = current;
                    current = current->right;
                }
            }//end if
            if (pred != NULL && current != NULL && pred->val > current->val){//找到待交换的2个数
                if (pred1 == NULL) { 
                    pred1 = pred; 
                    cur1 = current;
                }
                else {
                    pred2 = pred; 
                    cur2 = current; 
                } 
            }//end if
        }//end if

        int tmp;
        if (pred1 != NULL && cur2 != NULL){//pred1和cur2交换
            tmp = pred1->val;
            pred1->val = cur2->val;
            cur2->val = tmp;
        }
        else{                            //pred1和cur1交换
            tmp = pred1->val; 
            pred1->val = cur1->val; 
            cur1->val = tmp; 
        } 
    }
};

把原理弄清楚,自己实现一下。

原文地址:https://www.cnblogs.com/Xylophone/p/3893948.html