1. 程式人生 > >劍指offer 連結串列中環的入口節點

劍指offer 連結串列中環的入口節點

一個連結串列中包含環,請找出該連結串列的環的入口結點。

這個題目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步,然後兩個指標以相同的速度向前移動。
當第二個指標指向環的入口結點時,第一個指標已經圍繞著環走了一圈又回到了入口結點。
所以首先要得到環中結點的數目。

這個程式碼就不寫了