思路有点类似小学的相遇追及问题,一个速度快一个速度慢的两个人在跑道上匀速跑,若干圈后他们总会相遇,就用这个来证明链表中有环的存在。
官方原话:
当链表中不存在环时,快指针将先于慢指针到达链表尾部,链表中每个节点至多被访问两次。
当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。而初始距离为环的长度,因此至多移动
第二句话一开始没懂为什么是每一轮移动后距离减少1,后来感觉可以理解成快指针比慢指针早入环,当慢指针入环后可以理解成快指针在后面追,快指针速度是2,慢指针速度为1,每一轮后距离则减少1。
还有个点就是一开始一直在纠结快慢指针起点应该相同,所以一开始代码写成了这样:
ListNode* fast=head;
ListNode* slow=head;
但其实假如这样写的话,下面的
while(slow!=fast)
条件不满足,压根进不去就会直接返回true了。
/**
* 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) {
if(head==nullptr||head->next==nullptr){
return false;//判断是否为空链表或者只有一个节点,是则不是环形链表
}
ListNode* fast=head->next;
ListNode* slow=head;
while(slow!=fast){
if(fast==nullptr||fast->next==nullptr){
return false;//快指针到达链表尾部了还是没追上慢指针,说明不是环形链表
}
slow=slow->next;
fast=fast->next->next;
}
return true;
}
};