142. 環形鏈表 II

題目描述

給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。

爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。

說明:不允許修改給定的鏈表。

示例 1:

輸入:head = [3,2,0,-4], pos = 1
輸出:tail connects to node index 1
解釋:鏈表中有一個環,其尾部連接到第二個節點。
在這裏插入圖片描述

思路

  1. 環形鏈表,設置快慢指針,兩個指針如果相遇,鏈表存在環,不相遇,不存在環。
  2. 上面一條用於解決鏈表是否有環的問題,對於本題,如果有環,要返回鏈表中環的入口。
  3. 假設環的入口位置距離鏈表頭距離爲:xx, 快慢指針相遇位置距離環的入口位置距離爲:yycc爲環的長度,假設相遇時慢指針已經循環了n1n1次環。慢指針走過的長度爲(x+y+n1c)(x+y+n1*c),快指針一次走兩步是慢指針的一倍,所以快指針走過的長度爲(x+y+n1c)2(x+y+n1*c) * 2,則有一下關係:
    (x+y+n1c)2(x+y+n1c)=n2c (x+y+n1*c) * 2 - (x+y+n1*c) = n2*c
    化簡後爲:
    x+y=(n2n1)c x+y=(n2-n1)*c
    意味着:非環部分的長度+環入口到相遇點之間等於環的整數倍。當兩個指針在環中相遇時,已經走了yy,則再走xx 就能走若干個環。即在相遇點時,用兩個指針一個從相遇點出發一個從鏈表頭出發,相遇時就走了xx距離,達到了環的入口位置。
    畫一個圖計算一下!
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                fast = head;
                while (fast != slow) {
                    fast = fast->next;
                    slow = slow->next;
                }
                return slow;
            }
        }
        return NULL;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章