LeetCode#141-Linked List Cycle-環形鏈表

一、題目

給定一個鏈表,判斷鏈表中是否有環。

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

示例 1:

輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:鏈表中有一個環,其尾部連接到第二個節點。

示例 2:

輸入:head = [1,2], pos = 0
輸出:true
解釋:鏈表中有一個環,其尾部連接到第一個節點。

示例3:

輸入:head = [1], pos = -1
輸出:false
解釋:鏈表中沒有環。

進階:你能用 O(1)(即,常量)內存解決此問題嗎?

二、題解

  • 解法1:哈希表

遍歷所有節點並把每個節點的引用存儲到哈希表中。如果當前節點的引用已經存在於哈希表中,說明該鏈表是環形鏈表,返回 true;反之,則遍歷到尾,即該節點的下一個節點爲 null,該鏈表不是環形鏈表,返回 false。

時間複雜度:O(n),空間複雜度:O(n)。

function hasCycle($head) {
    $hashMap = [];
    $curr = $head;
    while ($curr != null && $curr->next != null) {
        if (in_array($curr, $hashMap)) {
            return true;
        } 
        $hashMap[] = $curr;
        $curr = $curr->next;
    } 
    return false;
}
  • 解法2:雙指針——快慢指針

快指針:一次兩步
慢指針:一次一步

假設一個環形賽道,兩個運動員 A 和 B,A 領先 B 一步:
在一個圓裏,速度快的 A 在跑了 n 圈後,一定能遇到速度慢的 B
——對應鏈表,就是兩個指針重合

如果不是圓,速度快的 A 一定先到達終點,則說明不存在環
——對應鏈表,就是結尾指針指向null

時間複雜度:O(n),空間複雜度:O(1)。

function hasCycle($head) {
    if ($head == null || $head->next == null) {
        return false;
    }
    //快慢指針
    $slow = $head;
    $fast = $head->next;
    while ($slow != $fast) {
        //沒有環,fast走到鏈表尾部,fast爲空或者fast的next爲空
        if ($fast == null || $fast->next == null) {
            return false;
        }
        $slow = $slow->next;
        $fast = $fast->next->next;
    }
    return true;
}

快慢指針法是看了題解後做出來的,一開始有點不明白:爲什麼快指針速度爲 2,慢指針速度爲 1?快指針速度不能爲 3 甚至更大嗎?

畫圖畫了幾遍,大概理解了:
fast 走 2 步,slow走 1 步,如果有環,則 fast 會碰到 slow 或者 fast 會走到 slow 的後面。

如果是 fast 走到 slow 後面,這時候兩個指針每走一次它們之間的距離就會縮小 1,最後無論多遠兩個指針肯定會相遇。

但是如果是 fast 走 3 步,slow 走 1 步,同樣是前面的情況,它們之間的距離每次縮小 2,最後 fast 又跑到 slow 前面去了,所以如果 fast 設置爲 3,需要多加一個判斷條件,見下面代碼 while 處。

function hasCycle($head) {
    if ($head == null || $head->next == null) {
        return false;
    }
    //快慢指針
    $slow = $head;
    $fast = $head->next->next;
    while ($slow != $fast || $slow->next != $fast) {
        //沒有環,fast走到鏈表尾部,fast爲空或者fast的next爲空
        if ($fast == null || $fast->next == null) {
            return false;
        }
        $slow = $slow->next;
        $fast = $fast->next->next->next;
    }
    return true;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章