

带环链表:尾节点的next指向链表中的任意节点。 那么环形链表怎么判断链表带不带环? 得考虑哪个节点是环里面的。 我们就会想到如果一个节点位置出现两次,那么就是进环了。但是并不能知道怎么判断位置重复出现。什么时候进环,又不知道。
这里用快慢指针最合适。

当两个指针都进入环以后,slow开始追击fast,到某一个位置会相遇。 只有两个指针都进入环才会相遇。

假设将起点到入环口点距离记为L,入口点到相遇点的位置记为X,环的长度记为C。 从开始位置相遇时slow走的距离是L+X,从开始点相遇时到fast走的距离是L+n*C+X。因为不知道在slow进环之前,fast已经在环里转了多少圈了,就设为n。

结论:一个指针从相遇点开始走,一个指针从头开始,它们会在入口点相遇。
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode *slow,*fast;
slow=fast=head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
struct ListNode *meet=slow;
while(head!=meet)
{
head=head->next;
meet=meet->next;
}
return meet;
}
}
return NULL;
}


与上一题类似,也使用快慢指针,不同的是这里不需要找出相遇点的位置,只需要判断是不是有环就行。 如果slow走一步fast走2步一定会相遇,为什么呢? slow进环后,fast和slow的距离每次追击都会缩减1。 假设slow进环时,fast与slow之间的距离为N。

如果slow一次走一步,fast一次走3步一定会相遇吗? 此时距离变化就是:这里就得分情况了

总之;
如果slow一次走n步,fast一次走m步,一定会相遇吗?(m>n>1) 这时缩小的距离是m-n,如果满足N%(m-n)==0就能追上。
bool hasCycle(struct ListNode *head) {
struct ListNode *slow,*fast;
slow=fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
return true;
}
}
return false;
}
有问题请指出,大家一起进步!