循環リンクリスト
リンクリストを指定して、リンクリストがループに入り始める最初のノードを返します。リンクリストにリングがない場合は、nullが返されます。
アイデア:高速ポインタと低速ポインタ、高速ポインタは一度に2ステップ、低速ポインタは一度に1ステップ、リングがある場合、高速ポインタはリング内の低速ポインタに追いつきます
/**
* 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, *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast) //如果链表存在环
{
fast = head;
while(fast != slow)//第二次相遇即为环的入口
{
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return NULL;
}
};
题解
このうち、[*]は高速ポインタと低速ポインタが最初に出会うポイント、リングに入る前の距離は[D]、低速ポインタがリングに入った後の移動距離は[S1]、残りの距離はリングは[S2]です
最初の遭遇
1.遅いポインターS = D + S12
。速いポインターF = D + n(S1 + S2)+ S1 n> = 1の場合、速いポインターは少なくとも複数の円を歩いた後に出会う可能性があり
ます3.またF = 2Sであるため、低速ポインタは1ステップ、高速ポインタは2ステップかかります
。4。1、2を代入して2(D + S1)= D + n(S1 + S2)+ S1
を取得します。さまざまなシフト項目を取得できます。 D =(n-1)S1 + nS2 =(n-1)(S1 + S2)+ S2
5.ここで、nは高速ポインターの回転数
n = 1 D = S2
n = 2 D = 1回転+ S2
n = 3 D = 2ターン+ S2
…
実際、何周するかは関係ありません。nラップ+ S2がエントリポイントであることがわかります
。6 。衝突の機会を人為的に構築し、クイックポインタを開始させます再び(ただし、今回は一度に1ステップずつ)スローポインターがリング内を何度回っても、リングの位置。
参考記事
LeetCodeリンク