ASP.NET AJAX(3)__UpdatePanel
給定一個連結串列的頭節點 head ,返回連結串列開始入環的第一個節點。 如果連結串列無環,則返回 null。
如果連結串列中有某個節點,可以通過連續跟蹤 next 指標再次到達,則連結串列中存在環。 為了表示給定連結串列中的環,評測系統內部使用整數 pos 來表示連結串列尾連線到連結串列中的位置(索引從 0 開始)。如果 pos 是 -1,則在該連結串列中沒有環。注意:pos 不作為引數進行傳遞,僅僅是為了標識連結串列的實際情況。
不允許修改 連結串列。
示例 1:
輸入:head = [3,2,0,-4], pos = 1 輸出:返回索引為 1 的連結串列節點 解釋:連結串列中有一個環,其尾部連線到第二個節點。
示例 2:
輸入:head = [1,2], pos = 0 輸出:返回索引為 0 的連結串列節點 解釋:連結串列中有一個環,其尾部連線到第一個節點。
提示:
連結串列中節點的數目範圍在範圍 [0, 104] 內
-105 <= Node.val <= 105
pos 的值為 -1 或者連結串列中的一個有效索引
進階:你是否可以使用 O(1) 空間解決此題?
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ structListNode *detectCycle(struct ListNode *head) { struct ListNode *slow = head; struct ListNode *fast = head; while(fast != NULL){ slow = slow->next; if (fast->next == NULL) { return NULL; } fast = fast->next->next; if (fast == slow){struct ListNode *node = head; while(node != slow){ node = node->next; slow = slow->next; } return node; } } return NULL; }
我們使用兩個指標,\textit{fast}fast 與 \textit{slow}slow。它們起始都位於連結串列的頭部。隨後,\textit{slow}slow 指標每次向後移動一個位置,而 \textit{fast}fast 指標向後移動兩個位置。如果連結串列中存在環,則 \textit{fast}fast 指標最終將再次與 \textit{slow}slow 指標在環中相遇。
如下圖所示,設連結串列中環外部分的長度為 aa。\textit{slow}slow 指標進入環後,又走了 bb 的距離與 \textit{fast}fast 相遇。此時,\textit{fast}fast 指標已經走完了環的 nn 圈,因此它走過的總距離為 a+n(b+c)+b=a+(n+1)b+nca+n(b+c)+b=a+(n+1)b+nc。
根據題意,任意時刻,\textit{fast}fast 指標走過的距離都為 \textit{slow}slow 指標的 22 倍。因此,我們有
a+(n+1)b+nc=2(a+b) \implies a=c+(n-1)(b+c)
a+(n+1)b+nc=2(a+b)⟹a=c+(n−1)(b+c)
有了 a=c+(n-1)(b+c)a=c+(n−1)(b+c) 的等量關係,我們會發現:從相遇點到入環點的距離加上 n-1n−1 圈的環長,恰好等於從連結串列頭部到入環點的距離。
因此,當發現 \textit{slow}slow 與 \textit{fast}fast 相遇時,我們再額外使用一個指標 \textit{ptr}ptr。起始,它指向連結串列頭部;隨後,它和 \textit{slow}slow 每次向後移動一個位置。最終,它們會在入環點相遇。