在鏈表學習中,我們已經了解了單鏈表和雙鏈表,兩者的最后一個結點都會指向NULL;今天我們介紹的循環列表則不同,其末尾結點指向的這是鏈表中的一個結點。
循環鏈表是一種特殊類型的鏈表,其尾節點的指針指向頭節點,形成一個閉環。與普通鏈表相比,它沒有明確的結束節點,遍歷時可無限循環。這種結構特別適合處理循環任務,如音頻播放列表循環播放、任務調度等場景,能有效減少節點訪問的邊界檢查,提高操作效率。
在循環鏈表的題目中,通常會涉及到兩個問題:
1.如何判斷該鏈表為循環鏈表
2.循環鏈表的循環入口位置。
力扣的142題就是循環鏈表題,以下是題解與代碼:
1、快慢指針尋找是否有環,
1).我們聲明兩個指針,快指針每次向鏈表下方走兩步,慢指針則走一步;
2).如果有環,則快指針先進入環,慢指針后進入環, 如果無環,則fast會走出循環判斷條件,返回空
3).有環時,慢指針進入環后,快指針相對慢指針每次移動一格,也就是快指針會追上慢指針。
4).快指針在一圈內追上慢指針:如果慢指針走一圈,快指針則走了兩圈,在這兩圈內,快指針一定會與慢指針相遇,所以快指針在一圈內追上慢指針
5).兩者相遇時、聲明index記錄該點。
2、如何判斷環的起點
head到起點記為 x;起點到相遇點記為y;相遇點再到起點記為z; 則y+z為環長,
慢指針與快指針所走距離差兩倍
x+y=n(y+z)
x=(n-1)(y+z)+z
也就是
入口距離=(n-1)圈長+相遇點到入口的距離
所以我們可以讓index 與head同時出發,兩者會同時到達入口,(該過程中index肯會繞環未知圈)
struct ListNode {int val;struct ListNode *next;
};
struct ListNode *detectCycle(struct ListNode *head)
{struct ListNode* fast=head,* slow=head;while (fast!=NULL&&fast->next!=NULL){fast=fast->next->next;slow=slow->next;if (slow==fast){struct ListNode* index;index=fast;while (index!=head){index=index->next;head=head->next;}return index;}}return NULL;
}
?
?