解题思路:
设置一个快指针fast,慢指针slow,都初始化为head(头结点)。
快指针一次走两步,慢指针一次走一步。
只要有环,快慢指针必定相遇!(推导可以去网上找,此处略)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
//快慢指针
ListNode* fast=head;
ListNode* slow=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast)return true;
}
return false;
}
};
解题思路:
这一题是上一题的升级,需要返回入环的第一个结点,然而上面的方法,假如链表有环,快慢指针虽然一定会相遇,但是这个相遇点不一定是入环的第一个结点。
找到入环的第一个结点的方法是:
1 先让slow和fast指针相遇
2 让slow=head(头结点),fast不动,然后一起往后走,一次走一步。
3 当两结点再次相遇,这次相遇的地方就是入环的第一个结点。
(这里只说方法,推导还是网上找 233,此处省略)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//不一定会在入口处相遇
//fast和slow相遇后,slow从head开始,fast不动,一起向前走,一次一步,两指针相交,交点即是入环的第一个结点
ListNode* fast=head;
ListNode* slow=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
//第一次相遇,说明有环
if(slow==fast){
//slow回到头结点
slow=head;
//没相遇之前,一起向后走
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}
};