这里非常巧妙地用到了两个指针,一个fast指针,每次跳两格,另一个slow指针,每次跳一格。将环形链表类比成环形操场跑步,不同速度的两个人一定会相遇。
//141. 判断单链表是否有环
/**
* 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 != nullptr && fast->next != nullptr)//fast最终为nullptr的话(到达链表末尾),说明是没有环;还要将一个元素的链表排除。负责下一步(fast->next->next)的操作属于未定义行为
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
return true;
}
}
return false;
}
};
//142. 判断单链表是否有环,有则返回链表开始入环的第一个节点
/**
* 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) {
if(head == nullptr) return nullptr;
ListNode* fast = head;
ListNode* slow = head;
while(fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
ListNode* p = head;//头部定义一个p指针
while(slow != p)//找到p和slow相遇的节点,该节点即为所求
{
slow = slow->next;
p = p->next;
}
return p;
}
}
return nullptr;
}
};