[leetcode] Recover Binary Search Tree

来源:互联网 发布:小霸王网络电视说明书 编辑:程序博客网 时间:2024/06/06 14:23

题目描述:

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的中序遍历是有序的”这一特征,就有如下两种情况值得考虑:

1   如果出现交换的两个数是相邻的

如:1 2 3 4 5 6 7,交换 2和3,得到 1  3  2  4  5  6  7 ,也就是说在交换之后形成的二叉树中会出现一对“反常”的数,如本例中的(3,2)

2 如果出现交换的数不是相邻的

如: 1 2 3  4 5 6 7    ,交换 2 和5 ,得到 1  5  3  4  2  6  7 ,也就是说在交换之后会有两对“反常”的数,如本例中的(5,3)和(4,2).

思路 1:使用中序遍历的非递归实现,利用栈可得到:

    void recoverTree(TreeNode *root) {        if(root == NULL)return;        stack< TreeNode *> s1;        TreeNode *node1 = NULL;        TreeNode *node2 = NULL;        TreeNode *pre = NULL;        while(root || !s1.empty())        {            while(root)            {                s1.push(root);                root = root->left;                continue;            }            root = s1.top();            s1.pop();                        if(pre && ( root->val < pre->val) )            {                if(node1 == NULL) node1 = pre; //当前值比后面的值大,那么pre一定是node1,root有可能是node2。因此必须将node2的值保存下来,如果再次遇到pre>root的情况的时候,那么现在的root就一定是node2.                //如果没有再次遇到pre>root的话,那么说明是相邻的两个节点出现了交换。                node2 = root;            }            pre = root;            root = root->right;        }        swap(node1->val,node2->val);        return;    }
关于上述两种情况的说明,已经在程序中注释证明了。时间复杂度为O(n).

由于我每一次只需要与前驱节点进行比较,因此使用Morris遍历,可将时间复杂度降低到O(1)。关于Morris中序遍历,参见Morris中序遍历,以及线索二叉树。

2   采用中序遍历的常数空间的版本。代码如下:

    void recoverTree(TreeNode *root) {        if(root == NULL)return;        TreeNode *ch1(NULL);        TreeNode *ch2(NULL);        TreeNode *pre(NULL);                while(root)        {            if(root->left == NULL)            {                if(pre && pre->val > root->val)                {                    if(ch1 == NULL) ch1 = pre;                    ch2 = root;                }                pre = root;                root = root->right;                continue;            }            TreeNode *temp = root->left;            for(;temp->right && temp->right != root; temp = temp->right);            if(temp->right == NULL)            {                temp->right = root;                root = root->left;            }            else            {                if(pre && pre->val > root->val)                {                    if(ch1 == NULL) ch1 = pre;                    ch2 = root;                }                temp->right = NULL;                pre = root;                root = root->right;            }        }        swap(ch1->val,ch2->val);        return ;    }
本题的难点应该在于,如果交换的是相邻的节点,那么只会出现一对反常的数。

0 0