1. 程式人生 > >劍指offer五十五之鏈表中環的入口結點

劍指offer五十五之鏈表中環的入口結點

coder 繼續 targe ext isp entry 2個 term next

一、題目

  一個鏈表中包含環,請找出該鏈表的環的入口結點。

二、思路

方法一:

技術分享

  假設x為環前面的路程(黑色路程),a為環入口到相遇點的路程(藍色路程,假設順時針走), c為環的長度(藍色+橙色路程)。

定義一個快指針:Sslow=slow.next,一個慢指針:Sfast=fast.next

當快慢指針相遇的時候:

  此時慢指針走的路程為Sslow = x + m * c + a ; 快指針走的路程為Sfast = x + n * c + a,則有:

      2 Sslow = Sfast

      2 * ( x + m*c + a ) = (x + n *c + a)

從而可以推導出:
      x = (n - 2 * m )*c - a
= (n - 2 *m -1 )*c + c - a
即環前面的路程 = 數個環的長度(為可能為0) + c - a
什麽是c - a?這是相遇點後,環後面部分的路程(橙色路程)。所以,我們可以讓一個指針從起點A開始走,讓一個指針從相遇點B開始繼續往後走,
2個指針速度一樣,那麽,當從原點的指針走到環入口點的時候(此時剛好走了x),從相遇點開始走的那個指針也一定剛好到達環入口點。所以2者會相遇,且恰好相遇在環的入口點。

  最後,判斷是否有環,且找環的算法復雜度為:時間復雜度:O(n),空間復雜度:O(1)

方法二:

  采用斷鏈法,訪問過的節點都斷開,最後到達的那個節點一定是循環的入口節點。

三、代碼

方法一代碼:

技術分享
/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        //檢驗
        if (pHead == null
|| pHead.next == null || pHead.next.next == null) { return null; } //定義快、慢指針 ListNode fast = pHead.next.next; ListNode slow = pHead.next; //先判斷有沒有環 while (fast != slow) { if (fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } else { //沒有環,返回 return null; } } //循環出來的話就是有環,且此時fast==slow,快慢指針在相遇點 fast = pHead;//快指針指向頭結點,慢指針在相遇點, while (fast != slow) { //以相同的速度前進,如果相遇,相遇點則為環的入口 fast = fast.next; slow = slow.next; } //返回環的入口 return slow; } }
View Code

方法二代碼:

技術分享
/*
下面的是斷鏈法,訪問過的節點都斷開,最後到達的那個節點一定是循環的入口節點。
*/
public class Solution2 {
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        if (pHead == null || pHead.next == null) {
            return null;
        }
        ListNode fast = pHead.next;
        ListNode slow = pHead;
        while (fast != null) {
            slow.next = null;
            slow = fast;
            fast = fast.next;
        }
        return slow;
    }
}
View Code

---------------------------------------------

參考鏈接:

https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4

劍指offer五十五之鏈表中環的入口結點