1 package algorithms;
2
3 /*
4 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
5
6 public class ListNode {
7 int val;
8 ListNode next = null;
9
10 ListNode(int val) {
11 this.val = val;
12 }
13 }
14 */
15
16 /*
17 * 首先判断链表中是否有环 思路是用两个指针,同时从链表的节点出发
18 * 一个走的慢,一个走的快
19 * 如果两个指针不能相遇则无环,否则有环
20 *
21 * 如何找到环的入口?
22 * 还是先定义两个指针,p1,p2
23 * n代表链表中环的节点个数
24 * p1先向前移动n步
25 * 然后两个指针以相同的速率向前移动
26 * 两个指针相遇的地方就是环的入口地址(总结规律出来的)
27 *
28 * 接下来就是如何求环中节点的个数
29 * 两个指针相遇的地方一定是在环的内部
30 * 所以可以从这个节点出发,边走边计数
31 * 当再次回到这个节点的时候 就知道环中节点的个数了
32 * */
33 public class EntryNodeOfLoop {
34
35 public ListNode EntryNodeOfLoop_1(ListNode pHead) {
36 //返回相遇的节点
37 ListNode meetingNode = meetingNode(pHead);
38 if (meetingNode == null)
39 return null;
40 int countOfLoop = 1;
41 ListNode node1 = meetingNode.next;
42 //求出圈的长度
43 while (node1 != meetingNode) {
44 countOfLoop++;
45 node1 = node1.next;
46 }
47 //p1向前移动圈长的长度
48 node1 = pHead;
49 for (int i = 0; i < countOfLoop; i++) {
50 node1 = node1.next;
51 }
52 //两个节点同时向前移动 相遇的地方就是圈的开始
53 ListNode node2 = pHead;
54
55 while (node1 != node2) {
56 node1 = node1.next;
57 node2 = node2.next;
58 }
59
60 return node1;
61
62 }
63
64 // 判断链表中是否有环 并找到相遇的节点
65 ListNode meetingNode(ListNode pHead) {
66 if (pHead == null)
67 return null;
68 ListNode slowNode = pHead;
69 ListNode fastNode = slowNode.next;
70 while (fastNode != null && slowNode != null) {
71 if (fastNode == slowNode)
72 return fastNode;
73 slowNode = slowNode.next;
74 fastNode = fastNode.next;
75 if (fastNode != null)
76 fastNode = fastNode.next;
77 }
78 return null;
79
80 }
81 }