
🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言 🔥专栏: 《C语言从零开始到精通》 《C语言编程实战》 《数据结构与算法》 《小游戏与项目》 💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。
基于 Floyd判圈算法(龟兔赛跑算法) ,核心目标是 不仅检测链表是否有环,还能找到环的入口节点。算法分为「环检测」和「入口定位」两个关键阶段
假设链表结构如下:
head 到环入口 entry 的距离为 L(节点数);C(环中节点数);slow 已走 S 步,快指针 fast 已走 2S 步(因快指针每次走2步,慢指针每次走1步,速度比2:1)。相遇时的关键结论:
2S - S = S,必然是环长度 C 的整数倍(快指针在环内绕圈追赶慢指针,多走的路程就是绕环的圈数),即 S = k*C(k 为正整数);S = L + M(M 是相遇点 meet 到环入口 entry 的距离,0 ≤ M < C);L + M = k*C → L = k*C - M → L = (k-1)*C + (C - M)。该式的物理意义:从链表头 head 到入口 entry 的距离 L,等于从相遇点 meet 绕环 (k-1) 圈后,再走到入口 entry 的距离(C - M 是相遇点到入口的剩余距离,绕 k-1 圈后回到相遇点,再走 C-M 步到入口)。
fast 和慢指针 slow 均指向链表头 head;fast != NULL && fast->next != NULL(避免快指针访问空指针崩溃);slow 每次走1步,fast 每次走2步;fast == slow,说明链表有环,记录相遇点 meet(meet = slow = fast),进入阶段2;若循环结束未相遇,说明无环,返回 NULL。pcur 指向链表头 head,meet 保持在之前的相遇点;pcur != meet;pcur 和 meet 每次均走1步(速度比1:1);pcur == meet 时,两指针同时到达环的入口节点,返回该节点(pcur 或 meet 均可)。fast、slow、meet、pcur),无额外空间开销;
typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head)
{
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
ListNode* meet = slow;
ListNode* pcur = head;
while(pcur != meet)
{
pcur = pcur->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}