Recover Binary Search Tree Leetcode Java

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?

题意:一颗二叉排序树,但是有两个元素顺序变了。让恢复这个二叉排序树。

最简单的思路就是,中序遍历这个排序树,将相应元素存到数组中,然后在数组中找到两个被交换的元素。
但是,这道题的要求只能使用O(1)的空间。

所以,就不能使用数组了。但是,我们可以使用类似的方法:即,也是中序遍历这个树,但是,需要将之前的节点存下来。如果之前节点的值大于当前节点的值,那么说明之前的节点有问题,将之前的节点存下来:

接下来,有两种情况:
(1)相邻的两个元素被交换,即问题节点1的下一个节点就是问题节点2。
(2)被交换的不是相邻的元素。

程序如下(需要注意,在该程序中,以上两种情况都能被处理):

public class RecoverBinarySearchTree {
    TreeNode firstElement = null;
    TreeNode secondElement = null;
    // The reason for this initialization is to avoid null pointer exception in the first comparison when prevElement has not been initialized
    TreeNode prevElement = new TreeNode(Integer.MIN_VALUE);

    public void recoverTree(TreeNode root) {

        // In order traversal to find the two elements
        traverse(root);

        // Swap the values of the two nodes
        int temp = firstElement.val;
        firstElement.val = secondElement.val;
        secondElement.val = temp;
    }

    private void traverse(TreeNode root) {

        if (root == null)
            return;

        traverse(root.left);

        // Start of "do some business", 
        // If first element has not been found, assign it to prevElement (refer to 6 in the example above)
        if (firstElement == null && prevElement.val >= root.val) {
            firstElement = prevElement;
        }

        // If first element is found, assign the second element to the root (refer to 2 in the example above)
        if (firstElement != null && prevElement.val >= root.val) {
            secondElement = root;
        }        
        prevElement = root;

        // End of "do some business"

        traverse(root.right);
}
}

其实原本,这道题做到这儿应该就完了,而且leetcode也可以通过,但是,讨论区某些人觉得,以上的解法由于使用到了递归,所有,需要的空间并不是O(1),而是O(lgn),不符合题意,如果需要满足题意,那么就需要使用morris方法遍历。

morris方法是个蛋蛋?!?morris方法,无非是通过时间换空间的一种方法,但是感觉时间复杂度较高,不太适用。关于morris方法,具体可以参加另一篇博客:
http://blog.csdn.net/zuoyexingchennn/article/details/45445891
适用morris方法的程序如下:

        public void recoverTree2(TreeNode root) {
            List<TreeNode> eNodes = new LinkedList<TreeNode>(); //error nodes
            if(root == null) return;
            TreeNode current = root;
            TreeNode pre;
            TreeNode previous = null;
            while(current != null){
                if(current.left == null){

                    if(previous!=null && previous.val > current.val){
                        eNodes.add(previous);
                        eNodes.add(current);
                    }
                    previous = current;
                    current = current.right;

                }else{
                    pre = current.left;
                    while(pre.right != null && pre.right.val != current.val){
                        pre = pre.right;
                    }

                    if(pre.right == null){
                        pre.right = current;
                        current = current.left;
                    }else {
                        if(previous!=null && previous.val > current.val){
                            eNodes.add(previous);
                            eNodes.add(current);
                        }

                        pre.right = null;
                        previous = current;
                        current = current.right;
                    }
                }
            }

            //this is redundant check
            //if(eNodes.size() == 0) return;

            if(eNodes.size() == 2){
                pre = eNodes.get(0);
                current = eNodes.get(1);
            }else{ //this case where eNodes.size()==4
                pre = eNodes.get(0);
                current = eNodes.get(3);
            }

            int temp = pre.val;
            pre.val = current.val;
            current.val = temp;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值