リンクリストを指定して、リンクリストがループに入り始める最初のノードを返します。リンクリストにリングがない場合は、nullが返されます。
特定のリンクリスト内のリングを表すために、整数posを使用して、リンクリストの終わりがリンクリストに接続されている位置を示します(インデックスは0から始まります)。posが-1の場合、リンクリストにリングはありません。posはリングを識別するためにのみ使用され、パラメーターとして関数に渡されないことに注意してください。注:指定されたリンクリストを変更することは許可されていません。
問題解決のアイデア:
1。高速ポインターと低速ポインターを使用して、ループがあるかどうかを判別します。低速ポインターを一度に1ステップ、高速ポインターを一度に2ステップ移動させます。
スピードポインタを使用してリングがあるかどうかを判断できる理由がわからない場合は、前のブログ「リングリンクリスト1」を読むことができます。
slow = slow->next;
fast = fast->next->next;
2.リングがある場合:高速と低速が合流し、ヘッドノードのヘッドと会議ノードを一度に1ステップずつ高速にします。
ヘッドと高速が合流すると、リングの最初のノードになります。
次の図に示すように、
Aはリンクリストのヘッドノードの位置、Bはエントリノードの位置、Cは高速ポインタと低速ポインタが出会う位置です。
AB = L、BC = Xとし、リングの円周をRとします。
CB = RC
高速ポインタと低速ポインタが出会うと:低速ポインタの距離はL + X、
高速ポインタは高速ポインタの移動距離に応じてL + X + n R
、低速ポインタは2回歩きます:
2 (L + X)= L + X + n Rを
解決できます:L = n * RX
L =(n-1)R +(RX)
コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
//创建快慢指针slow,fast
struct ListNode* slow = head,*fast = head;
//判断是否有环
while(fast && fast->next)
{
slow = slow->next;//慢指针每次走一步
fast = fast->next->next;//快指针每次走俩步
if(fast == slow)
{
break;//相遇跳出
}
}
if(fast == NULL || fast->next == NULL)//判断无环的情况
{
return NULL;
}
//有环
while(head != fast)//fast从与slow相遇的结点走,head从头开始走,head与fast相遇点就是环的头结点
{
head = head->next;
fast = fast->next;
}
return head;
}