一、题目
二、方案
1、Hash表
我们可以通过检查一个结点此前是否被访问过来判断链表是否为环形链表。常用的方法是使用哈希表。
我们遍历所有结点并在哈希表中存储每个结点的引用(或内存地址)。如果当前结点为空结点 null(即已检测到链表尾部的下一个结点),那么我们已经遍历完整个链表,并且该链表不是环形链表。如果当前结点的引用已经存在于哈希表中,那么返回 true(即该链表为环形链表)
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
bool hasCycle(ListNode *head) {
unordered_map<ListNode*,int> nodesSeen;
while (head != nullptr) {
if (nodesSeen[head]>1) {
return true;
}
else {
nodesSeen[head]++;
}
head = head->next;
}
return false;
}
2、双指针法
双指针法如下:快指针相当于环形跑道上领先的人,慢指针则是落后的人,如果存在环,那么快指针总会追上慢指针而相遇。快指针每次走两步,慢指针每次走一步,快指针相对于慢指针每次走一步
bool hasCycle(ListNode *head) {
//两个运动员位于同意起点head
ListNode* faster{ head }; //快的运动员
ListNode* slower{ head }; //慢的运动员
if (head == NULL) //输入链表为空,必然不是循环链表
return false;
while (faster != NULL && faster->next != NULL)
{
faster = faster->next->next; //快的运动员每次跑两步
slower = slower->next; //慢的运动员每次跑一步
if (faster == slower) //他们在比赛中相遇了
return true; //可以断定是环形道,直道不可能相遇
}
return false; //快的运动员到终点了,那就是直道,绕圈跑不会有终点
}
参考:
https://leetcode-cn.com/problems/linked-list-cycle/solution/simple-c-shuang-zhi-zhen-by-zrita/