• 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?

    难度:89. 这道题是要求恢复一颗有两个元素调换错了的二叉查找树。一开始拿到可能会觉得比较复杂,其实观察出规律了就比较简单。主要还是利用二叉查找树的主要性质,就是中序遍历是有序的性质。那么如果其中有元素被调换了,意味着中序遍历中必然出现违背有序的情况。那么会出现几次呢?有两种情况,如果是中序遍历相邻的两个元素被调换了,很容易想到就只需会出现一次违反情况,只需要把这个两个节点记录下来最后调换值就可以;如果是不相邻的两个元素被调换了,举个例子很容易可以发现,会发生两次逆序的情况,那么这时候需要调换的元素应该是第一次逆序前面的元素,和第二次逆序后面的元素。比如1234567,1和5调换了,会得到5234167,逆序发生在52和41,我们需要把4和1调过来,那么就是52的第一个元素,41的第二个元素调换即可。如果是1和3调换了,会得到3214567,逆序发生在32和21,那么需要调换的是32的第一个元素,21的第二个元素。所以我们要做的就是把逆序的所有元素都依次存在一个ArrayList里面,不管是一次逆序还是两次,只需要把一头一尾的两个元素完成值交换,就好了。


    搞清楚了规律就容易实现了,中序遍历寻找逆序情况,调换的第一个元素,永远是第一个逆序的第一个元素,而调换的第二个元素如果只有一次逆序,则是那一次的后一个,如果有两次逆序则是第二次的后一个。算法只需要一次中序遍历,所以时间复杂度是O(n),空间是栈大小O(logn)。

    Adopted approach:

     1 public class Solution {
     2     
     3     ArrayList<TreeNode> list;
     4     TreeNode prev;
     5     
     6     public void recoverTree(TreeNode root) {
     7         list = new ArrayList<>();
     8         prev = null;
     9         
    10         // In order traversal to find the two elements
    11         inorder(root);
    12         
    13         // Swap the values of the two nodes
    14         int temp = list.get(0).val;
    15         list.get(0).val = list.get(list.size() - 1).val;
    16         list.get(list.size() - 1).val = temp;
    17     }
    18     
    19     private void inorder(TreeNode cur) {
    20         
    21         if (cur == null)
    22             return;
    23             
    24         inorder(cur.left);
    25         
    26         if (prev != null && prev.val >= cur.val) {
    27             list.add(prev);
    28             list.add(cur);
    29         }
    30           
    31         prev = cur;
    32 
    33         inorder(cur.right);
    34     }
    35 }

    注意交换两个节点的做法,不能交换两个引用变量,这样对象不受影响,要改需要通过引用变量去访问对应的对象,去改对应对象的内容,只改引用变量的指向对于对象不会有影响

  • 相关阅读:
    01背包
    用动态规划求两个自然数的最大公约数
    编程实现文件的复制功能,要求源文件名及目标文件名在程序运行后根据提示输入
    this和super
    JAVA中static的使用
    结构化异常处理 笔记
    继承和多态 笔记
    javascript 客户端验证和页面特效制作 学习笔记
    定义封装的类类型 笔记
    C# 核心编程结构Ⅱ 笔记
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/3980479.html
Copyright © 2020-2023  润新知