Linked List Cycle II

Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

題目大意:
給定一個鏈表,如果該鏈表中含有環,則返回這個環開始的那個節點的地址,如果沒有環,則返回NULL.

原題鏈接: https://leetcode.com/problems/linked-list-cycle-ii/

這個題目接Linked List Cycle, 也是快慢指針的運用.示意圖如下:
示意圖

如上圖, 在環的前面,長度爲a(即, 從頭結點開始,走a步到環的入口), 環的周長爲b(即,從環的入口開始,走b步回到入口處).

那麼快慢指針每次分別走2步和1步,設走了x步相遇,則:
(2xa)(xa)=nb;n=0,1,2,...

則,可知:
x=nb;n=0,1,2,...

那麼,相遇點從環入口處計數,已經走了 nba (步),換句話說, 這個時候再走 a (步)就可以到環的入口處. 如果這個時候再有一個指針,從鏈表頭開始走, 也正好走 a (步) 可以到環入口處.

綜上,設快慢指針相遇點爲meet, 令一個指針爲p, p從頭指針出開始走, 每次走一步, meet也跟隨p每次走一步.那麼他們會在環的入口處相遇.

代碼如下:

 // 有環的話,返回快慢指針相遇的地址;
 // 無環的話,返回NULL
 struct ListNode* judgeCycle(struct ListNode *head) {


    int slowStep = 1;
    int fastStep = 2;
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (true) {
        for (int j = 0; j < fastStep; ++j) {
            fast = fast->next;
            if (NULL == fast) {
                return NULL;
            }
        }
        for (int i = 0; i < slowStep; ++i) {
            slow = slow->next;
        }
        if (fast == slow) {
            return fast;
        }
    }
}
struct ListNode *detectCycle(struct ListNode *head) {
    if ((NULL == head) || (NULL == head->next)) {
        return NULL;
    }

    struct ListNode* p = head;
    struct ListNode* meet = judgeCycle(head);
    if (NULL == meet) {
        return NULL;
    }

    while (true) {
        if (p == meet) {
            return p;
        }
        p = p->next;
        meet = meet->next;
    }
}
發佈了26 篇原創文章 · 獲贊 106 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章