1. 程式人生 > 其它 >尋找單向環形連結串列的交點(C語言)

尋找單向環形連結串列的交點(C語言)

聽說這題還是挺有邏輯性的,我們來看看吧

題目


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
`struct ListNode *detectCycle(struct ListNode *head) {}`

連結:https://leetcode-cn.com/problems/linked-list-cycle-ii/

示例

分析

思路一:

我們可以利用快慢指標,慢指標每次走一步,快指標每次走兩步,如果這個單向連結串列無環,則慢指標永遠都追不上快指標;但是如果有環,就必定在某一點上回相遇;

證明一下為什麼快慢指標一定會相遇:

首先快指標一定比慢指標先進環,假設慢指標剛好到環的起點第一個位置,例如示例中“2”的位置,那麼他們差的距離記作X,按照剛剛的邏輯“慢指標每次走一步,快指標每次走兩步”,X每次就減少一,那麼X作為一個整數,當X = 0時,慢指標跟快指標差距為0,不就是相遇了。

繼續剛剛的相遇,若相遇,則我們把相遇的點斷開,那麼環就變成了相交的連結串列,最後我們就可以按照相交連結串列的求法來解決這個問題

總結

這個方法寫起來複雜,但理解起來很簡單,斷開這個具體的操作就是把相遇點的下一個節點記錄,然後把相遇點指向NULL即可,相交連結串列問題就是長的連結串列可以先走上兩連結串列的長度差值步,然後再比較節點地址即可

思路二:

還是用快慢指標,如果有環必相遇,如果沒環結束。但是這次我們相遇後,讓這個連結串列的頭結點開始移動,fast/slow指標任意一個移動,計較,最後必定會走到同一個點上,而這個點就是我們要找的

證明:

總結

這個程式碼好寫,但是理解起來不容易,值得反覆觀看這個過程。

思路二的程式碼

typedef struct ListNode Node;
struct ListNode *detectCycle(struct ListNode *head) {
    Node* slow = head;
    Node* fast = head;
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            Node* intersection = slow;
            while (intersection - head)//有環,頭走,slow跟fast的交點走,相同就是環的起點
            {
                intersection = intersection->next;
                head = head->next;
            }
            return intersection;
        }
    }
    return NULL;//無環
}

如果看完對你有一點啟發,可以點個贊嗎?感謝!

更新
2022.3.11
10:17