链表中的环是很经典的面试题,重要的是掌握链表类题目中快慢双指针的用法,不光可以用来解决环的探测,也可以解决其他的问题,例如查找链表中倒数第N个数,只要让fast比slow指针快N个节点,然后两个指针一起前进,当fast走到链表尽头,slow就指向倒数第N个节点(这道LC题前几天做到了,但是忘记是哪一道了)。
LC 141 Linked List Cycle
bool hasCycle(ListNode *head) {
if(head==NULL||head->next==NULL)
return false;
ListNode *f=head,*s=head;
while(f->next&&f->next->next){
f=f->next->next;
s=s->next;
if(f==s)
return true;
}
return false;
}
LC142 Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
我在代码里已经把解题思路写好了,这里就直接复制过来了。
L1: distance from head to the entry point of cycle
L2: distance from the entry point to meeting pointC: number of points in the cycle
When the slow pointer enters the cycle, if the cycle is long enough, the fast pointer is L1 points ahead of slow.
Then the chase within cycle starts. The slow walks L2 steps and the fast walks 2 * L2 steps.
We have this equation: place of fast + steps that fast walked - n loops == steps that slow walked, that is :
L1 + 2 * L2 - n * C == L2 ===> L1 + L2 == n * C
******IMPORTANT CONCLUSION******: distance from meeting point to entry point along the forward direction == L1
If there is only one loop, then L1 + L2 == C, or L1 = C - L2
Therefore, if we start from the meeting point, let A start from head and B start from meeting point, both walks by one step,
then A and b shall meet at the entry point of the cycle.
通过数学方法寻找到L1,L2和C的关系,在slow和fast相遇时,让a从head开始,b从相遇点开始,两个指针相遇的地方就是环开始的地方。知道这个结论之后就可以很简单的做出这道题了。所以感觉这道题更像一道数学题而不是链表题。
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head,*fast = head;
while(slow != NULL && fast != NULL && fast->next != NULL) {
slow = slow->next; //Slow moves by 1 step
fast = fast->next->next; //Fast moves by two steps
//If they meet then there is a loop
if(slow == fast)
{
//To find the starting element where the loop starts
fast = fast;
slow = head;
while(slow != fast)
{
//Both move by 1 step
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return NULL;
}