zoukankan      html  css  js  c++  java
  • LeetCode——恢复二叉搜索树

    Q:二叉搜索树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。

    A:
    1.中序遍历 根据出现降序的次数 找出两个错误的节点,交换节点值

    • 只出现一次降序 则第一个为降序时较大的,第二个为降序时较小的
    • 出现了两次降序 则第一个为第一次降序时较大的,第二个为第二次降序时较小的
      public void inorder(TreeNode root, List<Integer> nums) {
        if (root == null) return;
        inorder(root.left, nums);
        nums.add(root.val);
        inorder(root.right, nums);
      }
    
      public int[] findTwoSwapped(List<Integer> nums) {
        int n = nums.size();
        int x = -1, y = -1;
        for(int i = 0; i < n - 1; ++i) {
          if (nums.get(i + 1) < nums.get(i)) {
            y = nums.get(i + 1);
            // first swap occurence
            if (x == -1) x = nums.get(i);
            // second swap occurence
            else break;
          }
        }
        return new int[]{x, y};
      }
    
      public void recover(TreeNode r, int count, int x, int y) {
        if (r != null) {
          if (r.val == x || r.val == y) {
            r.val = r.val == x ? y : x;
            if (--count == 0) return;
          }
          recover(r.left, count, x, y);
          recover(r.right, count, x, y);
        }
      }
    
      public void recoverTree(TreeNode root) {
        List<Integer> nums = new ArrayList();
        inorder(root, nums);
        int[] swapped = findTwoSwapped(nums);
        recover(root, 2, swapped[0], swapped[1]);
      }
    
    

    2.为了满足空间复杂度为O(1),使用Morris遍历算法
    Morris遍历算法 具体内容查看Morris遍历算法

    代码:

        public void recoverTree(TreeNode root) {
            //x存小索引那个结点,y存大索引那个结点,pre存前驱结点
            TreeNode x = null, y = null, pred = null;
            TreeNode node = root;
            while (node != null) {
                if (node.left == null) {
                    if (pred != null && node.val < pred.val) {
                        if (x == null)
                            x = pred;
                        y = node;
                    }
                    pred = node;
                    node = node.right;
                } else {
                    TreeNode predecessor = node.left;
                    while (predecessor.right != null && predecessor.right != node) {
                        predecessor = predecessor.right;
                    }
                    if (predecessor.right == null) {
                        predecessor.right = node;
                        node = node.left;
                    } else {
                        if (pred != null && node.val < pred.val) {
                            if (x == null)
                                x = pred;
                            y = node;
                        }
                        pred = node;
                        predecessor.right = null;
                        node = node.right;
                    }
                }
            }
            int t = x.val;
            x.val = y.val;
            y.val = t;
        }
    
  • 相关阅读:
    连接MySQL错误:Can't connect to MySQL server (10060)
    PHP性状的使用
    PHP interface(接口)的示例代码
    jquery 设置页面元素不可点击、不可编辑、只读(备忘)
    ace_admin_1.3.1 wysiwyg 工具条下拉出不来
    类函数和对象函数 PHP
    PHP 回调、匿名函数和闭包
    simplexml_load_file 抑制警告的直接输出
    jQuery判断当前元素是第几个元素
    hihocoder #1445 : 后缀自动机二·重复旋律5
  • 原文地址:https://www.cnblogs.com/xym4869/p/12936007.html
Copyright © 2011-2022 走看看