LeetCode 141.帶環問題(判斷是否帶環) 142.帶環問題(返回入環點)

1.帶環問題(判斷是否帶環)

(1)題目描述

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

如果鏈表中有某個節點,可以通過連續跟蹤 next 指針再次到達,則鏈表中存在環。 爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。注意:pos 不作爲參數進行傳遞,僅僅是爲了標識鏈表的實際情況。
如果鏈表中存在環,則返回 true 。 否則,返回 false 。

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



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


使用語言: C語言


(2)思路解析

此題可以用快慢指針解決,給兩個指針分別指向鏈表的頭節點,慢指針走一個節點快指針走兩個節點,當快指針爲空或快指針的next爲空,則不帶環。若快指針指向和慢指針直指向的同一位置,則證明此鏈表帶環,且二者必在環裏相遇

a.問題: 怎麼證明快指針和慢指針一定會在環裏相遇,而不是一直錯過?

在這裏插入圖片描述

b.問題:如果slow一次走一步,fast一次走3步?fast一次走4步?fast一次走n步?能追上嗎?

結論:不一定能追上
如果slow一次走一步,fast一次走3步,它們之間的差距就是
n-2
n-4
n-6

如果差距是0就追上了,相當於slow在原地不動,fast每次走兩步,以減小兩者之間的差距,那麼說明如果n是偶數,就能追上,n是奇書就會錯過,最特殊的情況錯過之後,差距還是奇數,那麼就會永遠追不上
如果fast每次走4/5/…/n步是同樣的道理






(3)代碼實現

bool hasCycle(struct ListNode *head) 
{
   
   
    struct ListNode * slow = head;
    struct ListNode * fast = head;
    //若fast或fast->next爲空不帶環
    while(fast && fast->next)
    {
   
   
        slow = slow->next;
        fast = fast->next->next;
        //若兩個指針指向同一位置,則代換
        if(fast == slow)
        return true;
    }
    return false;
}

2.帶環問題(返回入環點)

(1)題目描述

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

爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。注意,pos 僅僅是用於標識環的情況,並不會作爲參數傳遞到函數中。
說明:不允許修改給定的鏈表。

示例1
在這裏插入圖片描述
輸入:head = [3,2,0,-4], pos = 1
輸出:返回索引爲 1 的鏈表節點
解釋:鏈表中有一個環,其尾部連接到第二個節點。


示例2
在這裏插入圖片描述
輸入:head = [1], pos = -1
輸出:返回 null
解釋:鏈表中沒有環。


使用語言: C語言





(2)思路解析

給兩個指針分別指向鏈表的頭節點,慢指針走一個節點快指針走兩個節點,當快指針爲空或快指針的next爲空,則不帶環。若快指針指向和慢指針直指向的同一位置,則證明此鏈表帶環,且二者必在環裏相遇,保存兩個指針相遇的位置到給指針meet,此時meet位置距離入環節點的位置剛好等於head到入環節點的位置,此時只需讓meet和head同時走,二者相遇的位置就是入環節點的位置

圖解如下:
在這裏插入圖片描述

(3)代碼實現

struct ListNode *detectCycle(struct ListNode *head) 
{
   
   
        struct ListNode * fast = head;
        struct ListNode * slow = head;
        //先判斷是否帶環
        while(fast && fast->next)
        {
   
   
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
            {
   
   
                //相遇的節點給meet
                struct ListNode * meet = slow; 
                //帶環,給兩個指針一個head一個meet,兩個指針同時走,直到相遇,相遇點就是入環的節點
                 while(meet != head)
                 {
   
   
                     head = head->next;
                     meet = meet->next;
                }
                return head;
            }
        }
        return NULL;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章