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

這個代碼就不寫了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章