zoukankan      html  css  js  c++  java
  • 99. Recover Binary Search Tree

    看答案做出来了,其实做的并不好,中间被各种cases虐。

    思路其实并不难,in-order traversal是肯定的,顺序是从小到大。
    当前应该比前一个大,如果cur < prev,说明prev有问题,那么发现第一个;
    找第二个的时候有所不同,还是继续in-order往后走,一旦发现cur < prev,那cur有问题,而不是prev有问题。

    第一次做写到这我觉得找到俩了,直接break(return),然后发现不对。

    有一种可能是检测某一个NODE的时候,实际上是prev和cur都有问题,需要他俩交换一下。
    比如[1,2,3],从2回到1的时候,prev是2,cur是1,俩都有问题。所以在不满足sorted的情况下,更新第二个错误的node的时机是,只要第一个发现了第二个就必须,为了防止[1,2,3]的情况。
    这里的问题是弄不好只有prev是错的,cur是对的。
    比如[2,3,1],从坐支3回到2的时候,出现问题,那么左支3(prev)肯定有问题,但是2是无辜的。。有问题的是2(cur)的右支1.

    所以还要继续。。如果找不到不是sorted的了,那就是刚才的和node1一起更新的那个node2,找到了就是新更新的node2。

    简而言之第二次找到不符合规定的才算数。。

    做得并不好,修修补补看错误的test cases才改出来。 回想一下以前1刷2刷经常是这么修出个答案还觉得做出来了,唉。。

    Time: O(n)
    Space: O(n)

    public class Solution {
        TreeNode first = null;
        TreeNode second = null;
        TreeNode prev = null;
        public void recoverTree(TreeNode root) {
            inOrder(root);
            int temp = first.val;
            first.val = second.val;
            second.val = temp;
            return;
        }
        
        public void inOrder(TreeNode root) {
            if (root == null) return;
    
            inOrder(root.left);
            
            if (prev != null && prev.val >= root.val) {
                if (first == null) {
                    first = prev;
                } 
                if (first != null) {
                    second = root;
                }
            }
            prev = root;
            inOrder(root.right);
            
        }
    }
    

    迭代的大同小异,也是O(n)

    真正意义上的Space O(1)其实是用Morris - traversal,然而第一次听说。

    .....
    ........

    研究了好久。

    遍历左支的时候,找最右,然后连回root,每个SubTree都这样。。

    看了代码不难理解,但是让我自己写估计要想好一会,先这样了。。二刷再说。

    public class Solution {
        public void recoverTree(TreeNode root) {
            TreeNode prev = null;
            TreeNode first = null;
            TreeNode second = null;
            TreeNode extra = null;
            TreeNode temp = root;
            
            while (temp != null) {
                // out of order node detection part.
                if (prev != null && temp.val <= prev.val) {
                    if (first == null) {
                        first = prev;
                    }
                    second = root;
                }
                
                // Morris
                if (temp.left != null) {
                    extra = temp.left;
                    while(extra.right != null && extra.right != temp) {
                        extra = extra.right;
                    }
                
                    // going deep prcess is actaully hiding here...
                    if(extra.right == temp) {
                        extra.right = null;
                        prev = temp;
                        temp = temp.right;
                    }else{
                        extra.right = temp;
                        temp = temp.left;
                    }
                    // and here..
                } else {
                    prev = temp;
                    temp = temp.right;
                }
            }
            
            int temp = first.val;
            first.val = second.val;
            second.val = temp;
        }
        
       
    }
    

    Amazon OA2 做完还是没消息,神啊。。保佑我把,对我来说是救命的。。



    二刷。

    上午研究了一下Morris,找到这个题又来了一遍。

    我是先写好了morris in-order traversal,然后再把比较添加进去。

    代码里的 / / / / / visit / / / / /就是写traversal 的时候预留的actually visit node的地方。。然后在这些地方添加找错的代码。

    不如一刷简单,一刷只有一个判断的位置,在WHILE LOOP开头,但是乍看之下觉得说不通。。

    temp指针有三处移动的位置,我选择的2处是in-order的位置,另一处是pre order的位置,加在开始岂不是连pre order一起判断了么,顺序就不是sorted的了。。不知道怎么搞的。

    不想了。。

    public class Solution {
        public void recoverTree(TreeNode root) {
            TreeNode first = null;          // first messed up node
            TreeNode second = null;         // seond fucked up node
            TreeNode prev = null;           // previous pointer during traversal
            
            
            TreeNode temp = root;           // temp pointer during traversal
            TreeNode tail = null;           // tail pointer for morris traversal   
            
            while (temp != null) {
                
                if (temp.left != null) {
                    tail = temp.left;
                    //     find right most child  &&  2nd time we visit the node
                    while (tail.right != null && tail.right != temp) {
                        tail = tail.right;
                    }
                    
                    // first time we are here
                    if (tail.right == null) {
                        tail.right = temp;
                        temp = temp.left;
                    } else {
                        // 2nd time we are here
                        tail.right = null;
                        ////////// visit //////////
                        if (prev != null && temp.val <= prev.val) {
                            if (first == null) {
                                first = prev;
                            }
                            second = temp;
                        }
                        ////////// visit //////////
                        prev = temp;
                        temp = temp.right;
                    }
                } else {
                    /////////// visit /////////////
                    if (prev != null && temp.val <= prev.val) {
                        if (first == null) {
                            first = prev;
                        }
                        second = temp;    
                    }
                    /////////// visit //////////
                    prev = temp;
                    temp = temp.right;
                }
                
            }
            
            int tempVal = first.val;
            first.val = second.val;
            second.val = tempVal;
            return;
        }
    }
    
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/reboot329/p/6103971.html
Copyright © 2011-2022 走看看