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 }