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 }