zoukankan      html  css  js  c++  java
  • LeetCode OJ

    这道题要求空间复杂度为O(1),则只能采用Morris Traversal进行中序遍历!!这个了解了之后,难点在于如何定位到两个被交换了的节点?

    我就被困在这里几个小时!!!(允许我为自己的愚蠢表示下悲伤吧!!!)

    参考了discuss中前辈的算法,才发现很简单!!!

    我们只需要这样来看问题,BST的中序遍历是递增的,如果有一对节点被交换了,那么这个递增序列会在被交换的这对节点前后被打破。这一对节点有两种情况:一种是相邻着的,一种是不相邻的。对于第一种情况,我们只会遇到一次顺序被打破;而对于第二种情况,我们会遇到两次顺序被打破。当我们第一次遇到顺序被打破的时候,是中序遍历过程中上次被输出的节点和当前节点的值不满足小于的关系,而且可以肯定得是被交换的节点之一是上次被输出的节点,如果我们将不再遇到第二次顺序被打破,则说明是情况一,并且被交换的另一个节点是当前节点;如果我们会遇到第二次顺序被打破,同样这次也是中序遍历过程中上次被输出的节点和当前节点的值不满足小于的关系,并且可以肯定的是被交换的另一个节点是当前节点。

    通过上述过程可以确定被交换的两个节点,最后再互换这两个节点的值就可以了!!

     1 /**
     2      * Two elements of a binary search tree (BST) are swapped by mistake.
     3      * Recover the tree without changing its structure.
     4      * Could you devise a constant space solution?
     5      * using Morris Traversal
     6      * @param root
     7      */
     8     public void recoverTree(TreeNode root){
     9         if(root == null || root.left == null && root.right == null)
    10             return ;
    11         TreeNode pred1=null ;
    12         TreeNode cur1=null ;
    13         TreeNode pred2=null ;
    14         TreeNode cur2=null ;
    15         
    16         TreeNode cur = root;
    17         TreeNode last = null; // the last node that be printed out
    18         
    19         while(cur!=null){
    20         
    21             if(cur.left!=null){
    22                 //find its predecessor
    23                 TreeNode pre = cur.left;
    24                 while(pre.right!=null && pre.right != cur){
    25                     pre = pre.right;
    26                 }
    27                 if(pre.right == null)
    28                 {
    29                     pre.right = cur;//make the predecessor's right pointer points to the current node
    30                     cur = cur.left;
    31                 }else
    32                 {
    33                     pre.right = null;//recover the predecessor's right pointer.
    34                     last = cur;
    35                     cur = cur.right;// notice here!!!!!!
    36                 }                
    37                 
    38             }else{
    39                 last = cur;
    40                 cur = cur.right;
    41             }
    42             //it's a very nice method!!!!
    43             if(last!=null && cur != null && last.val>cur.val){
    44                 if(pred1 == null){
    45                     pred1 = last;
    46                     cur1 = cur;
    47                 }else
    48                 {
    49                     pred2 = last;
    50                     cur2 = cur;
    51                 }
    52             }
    53         }
    54         
    55         int temp ;
    56         if(pred1 != null && cur2 !=null){
    57             temp = pred1.val;
    58             pred1.val = cur2.val;
    59             cur2.val = temp;
    60         }else{
    61             temp = pred1.val;
    62             pred1.val = cur1.val;
    63             cur1.val = temp;
    64         }
    65         
    66     }
    有问题可以和我联系,bettyting2010#163 dot com
  • 相关阅读:
    Get-CrmSetting返回Unable to connect to the remote server的解决办法
    Dynamics 365中的常用Associate和Disassociate消息汇总
    Dynamics 365 Customer Engagement V9 活动源功能报错的解决方法
    Dynamics Customer Engagement V9版本配置面向Internet的部署时候下一步按钮不可点击的解决办法
    Dynamics 365检查工作流、SDK插件步骤是否选中运行成功后自动删除系统作业记录
    注意,更改团队所属业务部门用Update消息无效!
    Dynamics 365的审核日志分区删除超时报错怎么办?
    Dynamics 365使用Execute Multiple Request删除系统作业实体记录
    Dynamics 365的系统作业实体记录增长太快怎么回事?
    Dynamics CRM日期字段查询使用时分秒的方法
  • 原文地址:https://www.cnblogs.com/echoht/p/3710523.html
Copyright © 2011-2022 走看看