1.给定一个链表,判断链表中是否有环。
链表判断是否有环,使用快慢指针,快指针一次走两步,慢指针一次走一步,当快指针与慢指针相遇时,说明链表中有环。
问题:为什么快指针一次走两步,三次可以吗
答案:不可以,很有可能会一直错开
看图
bool hasCycle(struct ListNode *head) {
struct ListNode* fast=head;
struct ListNode* slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;//一次走两步
slow=slow->next;//一次走一步
if(fast==slow)//快指针追上慢指针则有环
return true;
}
return false;
}
找出环的入口点
2.给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL.
解题思路:
第一步找出两个指针的相遇点,第二步让快指针从相遇点开始走,让慢指针从链表的最开始走,快慢指针每次各走一步,当两个指针相遇了,即是入口点。
终极版原理
上面的是n=1的情况下
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode*fast=head;
struct ListNode*slow=head;
int pos=0;
//判断有没有环
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
{
pos=1;
break;
}
}
//在有环的基础上找出第一个入口
if(pos==1)
{
slow=head;
while(slow!=fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}return NULL;
}