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 }