给定一个链表,如何判断它是否有环?
最直观的思路是:如果能一路走到 NULL,说明没有环。
但为了更高效,我们使用 快慢指针 来解决。
判环思路
-
建立快指针
fast与慢指针slow。 -
每次循环:
slow走一步,fast走两步。 -
如果过程中出现
fast == slow,则说明链表存在环。 -
如果
fast、fast->next或fast->next->next为空,则链表无环。
struct ListNode * fast =head;
struct ListNode * slow =head;
while(fast&&fast->next&&fast->next->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
return true;
}
return false;
🔹 入环节点查找
当我们确定链表有环后,还可以进一步找出 入环的节点。
这个问题可以转化为 两个链表相交点 的问题:
-
相遇点记为
meet = fast->next; -
将
meet->next暂时断开,这样链表就被分成了两条; -
分别计算两条链表的长度差,长的先走差值步;
-
然后两条链表同步前进,第一次相遇的节点就是 入环节点。
struct ListNode * fast = head;
struct ListNode * slow = head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
break;
}
struct ListNode * meet = fast;
while(meet&&meet->next)
{
struct ListNode * newhead = meet->next;
meet->next=NULL;
while(1)
{
struct ListNode * new1 = newhead;
struct ListNode * new2 = head;
int count1=0;
int count2=0;
while(new1)
{
new1=new1->next;
count1++;
}
while(new2)
{
new2=new2->next;
count2++;
}
struct ListNode * newfast = newhead;
struct ListNode * newslow = head;
int c= count1-count2;
if(count1<count2)
{
newfast = head;
newslow=newhead;
c=count2-count1;
}
while(c--)
{
newfast=newfast->next;
}
while(newfast!=newslow)
{
newfast=newfast->next;
newslow=newslow->next;
}
meet->next=newhead;
return newfast;
}
}
return NULL;
5万+

被折叠的 条评论
为什么被折叠?



