一個鏈表中包含環,請找出該鏈表的環的入口結點。
這個題目leetcode上做到過,當時的思路是先找到快慢指針的第一次交點。然後把其中一個指針放回頭部,兩者以相同速度前進,相遇點即是入口,這需要數學證明,不大容易想
該方法代碼如下
public ListNode EntryNodeOfLoop(ListNode pHead){
ListNode slow = pHead;
ListNode fast = pHead;
while(slow != null && fast !=null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast) break;
}
if(fast == null || fast.next == null) return null;
slow = pHead;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
這次又多了兩種新思路:
這種方法會破壞鏈表的結構,但想法的確很不錯:
/*
時間複雜度爲O(n),兩個指針,一個在前面,另一個緊鄰着這個指針,在後面。
兩個指針同時向前移動,每移動一次,前面的指針的next指向NULL。
也就是說:訪問過的節點都斷開,最後到達的那個節點一定是尾節點的下一個,
也就是循環的第一個。
這時候已經是第二次訪問循環的第一節點了,第一次訪問的時候我們已經讓它指向了NULL,
所以到這結束。
*/
public ListNode EntryNodeOfLoop2(ListNode pHead){
if(pHead == null) return pHead;
ListNode pre = pHead;
ListNode cur = pHead.next;
while(cur != null){
if(pre.next == null) return pre;
ListNode tmp = cur;
cur = cur.next;
pre.next = null;
pre = cur;
}
return null;
}
其實還有一種比較常規的想法
如果鏈表中環 有n個結點,指針P1在鏈表上向前移動n步,然後兩個指針以相同的速度向前移動。
當第二個指針指向環的入口結點時,第一個指針已經圍繞着環走了一圈又回到了入口結點。
所以首先要得到環中結點的數目。
這個代碼就不寫了