【LeetCode】環形鏈表——不同角度解析

題目描述

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

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

示例

示例一:

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

示例二:

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

實例三:

輸入:head = [1], pos = -1
輸出:no cycle
解釋:鏈表中沒有環。
在這裏插入圖片描述

解題思路及完整代碼

1.巧用地址空間
因爲堆的地址從低到高,而LeetCode中的鏈表內存是順序申請的。所以如果鏈表中如果有環,head->next地址一定小於head。
代碼如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        while(head) {
            if(!less<ListNode *>()(head, head->next)) {
                return head->next;
            }
            head = head->next;
        }
        return nullptr;
    }
};

2. 用快慢指針法
慢指針每次向後走一步,快指針每次向後走兩步,因此快指針走過的路程一定是慢指針路程的兩倍。若鏈表中有環存在,則一定有以下規律。代碼如下:
在這裏插入圖片描述

代碼如下:

/*
 * 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* slow=head;
        ListNode* fast=head;
        while(slow)     //找到meet點
        {
            slow=slow->next;
            fast=fast->next;
            if(fast==NULL)  return nullptr;  //只有兩個節點且無環
            fast=fast->next;
            if(fast==NULL)  return nullptr;   //有三個節點且無環
            if(fast==slow)  break;       //即meet
        }
        slow=head;   //由 l=c-x 知,slow從head開始走到a點的距離,剛好是fast走到a點的距離
        while(slow!=fast)    //找到a點
        {
            slow=slow->next;
            fast=fast->next;
        }
        return slow;
    }
};

讀完記得關注博主喲~

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