Two nodes of a BST are swapped, correct the BST(恢复两个节点被交换的BST)

Two nodes of a BST are swapped, correct the BST(恢复两个节点被交换的BST)

Q:

BST的两个节点被交换了,修复它:

Input Tree:
         10
        /  \
       5    8
      / \
     2   20

In the above tree, nodes 20 and 8 must be swapped to fix the tree.  
Following is the output tree
         10
        /  \
       5    20
      / \
     2   8

Solution:

BST的按中序遍历生成排序数组。所以,一个简单的方法是将输入树的中序遍历结果存储在一个辅助数组中。对辅助数组进行排序。最后,将辅助数组元素插入BST,保持BST的结构不变。该方法的时间复杂度为O(nLogn),所需辅助空间为O(n)。

可以在O(n)时间内解决这个问题,只需对给定的BST进行一次遍历。由于BST的顺序遍历始终是一个排序数组,因此该问题可以简化为一个排序数组的两个元素交换的问题。我们需要处理两种情况:

  • 1.交换的节点在BST的排序顺序不相邻。
For example, Nodes 5 and 25 are swapped in {3 5 7 8 10 15 20 25}. 
 The inorder traversal of the given tree is 3 25 7 8 10 15 20 5 

在这里插入图片描述

如果仔细观察,在中序遍历中,会发现节点7比之前访问的节点25小。这里保存节点25(上一个节点)的上下文。同样,我们发现节点5比前一个节点20小。这一次,我们保存节点5(当前节点)的上下文。最后,交换两个节点的值。

  • 2.交换的节点在BST的中序遍历中是相邻的。
For example, Nodes 7 and 8 are swapped in {3 5 7 8 10 15 20 25}. 
  The inorder traversal of the given tree is 3 5 8 7 10 15 20 25 

在这里插入图片描述

与case1不同,此处仅存在一个节点值小于前一个节点值的点。节点7比节点8小。

如何解决?

  • 我们将保持三个指针,first、middle和last。
  • 当找到当前节点(current)值小于前一个节点(previous)值的第一个点时,我们用前一个节点(previous)更新first,middle用当前节点(current)更新。
  • 当我们找到当前节点(current)值小于前一个节点(previous)值的第二个点时,我们用当前节点(current)更新last。在case2中,我们永远找不到第二点。因此,last不会被更新。
  • 处理后,如果last为null,则BST的两个交换节点是相邻的。
    static class _1st_9 {
        public static void main(String[] args) {
            _1st_9 handler = new _1st_9();
            TreeNode root1 = TreeNodeIOUtils.transform("[10,8,20,25,null,15,5,3,7]");
            handler.printInOrder(root1);
            System.out.println();
//            handler.correctBST(root1);
            handler.printInOrder(root1);
            System.out.println();
            TreeNode root2 = TreeNodeIOUtils.transform("[10,7,20,5,null,15,25,3,8]");
            handler.printInOrder(root2);
            System.out.println();
            handler.correctBST(root2);
            handler.printInOrder(root2);
            System.out.println();
        }

        TreeNode first, middle, last;
        TreeNode prev;

        public void correctBST(TreeNode root) {
            correctBSTUtil(root);
            if (first != null && last != null) {//case1
                int t = first.val;
                first.val = last.val;
                last.val = t;
            } else if (first != null && middle != null) {//case2 last is null
                int t = first.val;
                first.val = middle.val;
                middle.val = t;
            }

        }

        public void correctBSTUtil(TreeNode root) {
            if (root == null) return;
            correctBSTUtil(root.left);
            if (prev != null && root.val < prev.val) {
                if (first == null) {
                    first = prev;
                    middle = root;
                } else {
                    last = root;
                }
            }
            prev = root;
            correctBSTUtil(root.right);
        }

        public void printInOrder(TreeNode root) {
            if (root == null) return;
            printInOrder(root.left);
            System.out.printf("%d ", root.val);
            printInOrder(root.right);
        }


    }

Reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值