环形链表
本文主要介绍如何判断一个链表是否是环形链表,以及如何得到环形链表中的第一个节点。
环形链表的介绍
环形链表是一种链表数据结构,环形链表是某个节点的next指针指向前面的节点或指向自己这个节点的一个链表,这个链表就构成了环形链表。
链表中是否带环
要判断一个链表中是否带环,首先直接给出结论,我们可以用一个快指针(一次走两步),应该慢指针(一次走一步),如果该链表带环,最后快指针和慢指针就会在环中相遇,否则就是快指针走到空,这就表明该链表不带环。
判断一个链表是否带环Leetcode
bool hasCycle(struct ListNode *head)
{
if(head==NULL)
return false;
struct ListNode *slow=head;
struct ListNode *fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
return true;
}
return false;
}
返回链表开始入环的第一个节点
返回链表开始入环的第一个节点Leetcode
使用快慢指针,快指针走两步慢指针走一步,它们两个一定会在环中相遇。此时一个从相遇点走,另一个从头节点开始走,两者同时走,当两者相遇时,这个相遇的节点就是入环的第一个节点。
根据这个思路代码如下:
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode *slow=head;
struct ListNode *fast=head;
if(fast==NULL||fast->next==NULL)
return NULL;
struct ListNode *ret=NULL;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
ret=slow;
break;
}
}
if(!fast||!fast->next)
return NULL;
struct ListNode *cur=head;
while(cur)
{
if(cur==ret)
return ret;
cur=cur->next;
ret=ret->next;
}
return NULL;
}
//找两个相交的链表
struct ListNode *firstcrossnode(struct ListNode *head1,struct ListNode *head2)
{
if(head1==NULL)
return NULL;
if(head2==NULL)
return NULL;
int len1=0;
int len2=0;
struct ListNode *cur1=head1;
struct ListNode *cur2=head2;
while(cur1)
{
cur1=cur1->next;
len1++;
}
while(cur2)
{
cur2=cur2->next;
len2++;
}
int len=abs(len1-len2);
struct ListNode *longlist=head1;
struct ListNode *shortlist=head2;
if(len1<len2)
{
longlist=head2;
shortlist=head1;
}
while(len--)
{
longlist=longlist->next;
}
while(longlist)
{
if(longlist==shortlist)
return longlist;
longlist=longlist->next;
shortlist=shortlist->next;
}
return NULL;
}
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode *slow=head;
struct ListNode *fast=head;
if(fast==NULL||fast->next==NULL)
return NULL;
struct ListNode *meet=NULL;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
meet=slow;
break;
}
}
if(!fast||!fast->next)
return NULL;
struct ListNode*newhead=meet->next;
meet->next=NULL;//将环形链表切割开
struct ListNode* cur=head;
//找第一个相交的链表
struct ListNode*ret=firstcrossnode(cur,newhead);
meet->next=newhead;//将链表还原回去
return ret;
}
总结:本文主要介绍了两个环形链表的经典问题,判断一个链表是否是环形链表以及得到环形链表的入口节点,从公式推到到代码的实现。感谢大家观看,如有错误不足之处欢迎大家批评指针!!!