输出链表环路入口节点

≡放荡痞女 提交于 2019-12-03 05:33:28
  1 package offer;
  2 
  3 import java.util.HashMap;
  4 import java.util.List;
  5 import java.util.Map;
  6 
  7 import Struct.ListNode;
  8 
  9 /**
 10  * 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
 11  * @author 爱不会绝迹
 12  *
 13  */
 14 public class Problem32 {
 15     /**
 16      * 我的解法,利用map标记每一个节点的出现的次数,第一个为出现次数为2的节点就是入口节点
 17      * @param pHead
 18      * @return
 19      */
 20      public static ListNode EntryNodeOfLoop(ListNode pHead)
 21      {
 22          Map<ListNode,Integer> map = new HashMap<>();
 23          ListNode p = pHead;
 24          while(p!=null){
 25              if(map.get(p)==null){
 26                  map.put(p, 1);
 27              }else{
 28                  return p;
 29              }
 30              p = p.next;
 31          }
 32         return null;
 33      }
 34 
 35     /**
 36      * 新的解法 ,追击问题模型,
 37      *         定义两个指针一快一慢,快指针速度为2,慢指针速度为1,两个指针从起点出发开始前进
 38      *
 39      *         当慢指针到达环路的入口时,在这个时候追击问题的模型形成,
 40      *         也就是说在这个时候,快指针在后面追慢指针,
 41      *             在这个时候有两个极端的情况,
 42      *             1、快指针在慢指针进入入口节点的时候两个指针相遇了,(这个时候的相遇是慢指针在环内走的最短的路程)
 43      *             2、快指针在慢指针后方一单位距离,(在这种情况下两个指针追击相遇的话就是慢指针在环内走的最长的路程)
 44      *                 在走最长路程的情况下,下面要论证的就是,在满指针走不超过一圈,快慢两指针必定相遇
 45      *                     现在的已知条件为快指针的速度为慢指针的速度的二倍,也就是说两指针的相对速度为1个单位,
 46      *                     如果说在慢指针静止的情况下,快指针会以1单位的速度前进,也就是说快指针追多不超过一圈就会遇到慢指针,
 47      *                     那么慢指针不静止呢,慢指针以单位1的速度前行,在慢指针走了一圈之后快指针,是不是就比慢指针多走一圈
 48      *                     然而快慢指针之间路程的差最大不超过一圈,所以说慢指针在进入环内不超过一圈就会被快指针追上
 49      *     现在设
 50      *         注意:链表是单向的
 51      *         a------------->开始点到环路入口的距离
 52      *         b------------->入口点到相遇点的距离
 53      *         c------------->相遇点到入口点的距离
 54      *
 55      *    那么相遇时
 56      *        快指针的路程    A = a+(b+c)*k+b
 57      *        慢指针的路程 B = a+b
 58      *
 59      *        A=2*B
 60      *
 61      *        2*(a+b)=a+(b+c)*k+b
 62      *        做一下提取化简
 63      *
 64      *        a = (K-1)(b+c)+c
 65      *    这个式子也就意味着,
 66      *        两个指针一样的速度,一个从起点出发一个从,相遇点出发当他们相遇的时候也就走的k-1倍环路长,也就是在环路的入口相遇
 67      *    这样就ok了    思路就出来了可以顺着写代码了
 68      *
 69      * @param pHead
 70      * @return
 71      */
 72     private static ListNode EntryNodeOfLoop2(ListNode pHead){
 73         ListNode p = pHead;
 74         ListNode meet = findMeetNode(pHead);
 75 
 76         while(p!=null&&meet!=null){
 77             if(p==meet){
 78                 return p;
 79             }
 80             p = p.next;
 81             meet = meet.next;
 82         }
 83         return null;
 84     }
 85     private static ListNode findMeetNode(ListNode pHead){
 86         ListNode fast = pHead;
 87         ListNode low = fast;
 88 
 89         while(fast!=null&&fast.next!=null){
 90             fast = fast.next.next;
 91             low = low.next;
 92             if(fast==low){
 93                 return low;
 94             }
 95         }
 96         return null;
 97     }
 98      public static void main(String[] args) {
 99         ListNode node1 = new ListNode(1);
100         ListNode node2 = new ListNode(2);
101         ListNode node3 = new ListNode(3);
102         ListNode node4 = new ListNode(4);
103         ListNode node5 = new ListNode(5);
104         
105         
106 //        node1.next = node2;
107 //        node2.next = node3;
108 //        node3.next = node4;
109 //        node4.next = node5;
110 //        node5.next = node3;
111         ListNode p = EntryNodeOfLoop2(node1);
112         System.out.println(p);
113     }
114 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!