题目要求
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
例图见 141. 环形链表
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
题解
https://leetcode-cn.com/problems/linked-list-cycle/solution/huan-xing-lian-biao-by-gpe3dbjds1/
标记法(leetcode无法提交)
下面的毁值法其实是根据这个方法改的,思路相同,只不过这个没法在leetcode上直接运行。
因为说好了有visit域,却没有。。。
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *q=head;
while(q)
{
if(q->visit==true)
return true;
else
q->visit=true;
}
return false;
}
};
毁值法(看看就好吧。。。)
思路也超简单,每路过一个节点就把值清0,如果没环肯定得遇到nullptr跳出循环return false,否则第二次遇到被标记的节点时就知道存在环了。
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL||head->next==NULL)
return false;
while(head->next&&head->val){
head->val=NULL;
head=head->next;
}
if(!head->next) return false;
return true;
}
};
执行用时 | 内存消耗 |
---|---|
16 ms | 10 MB |
快慢指针法(官方推荐)
- 初始化 slow = head->next,每次走一步
- 初始化 fast =head->next->next,每次走两步,每走一步判断一次
- 存在环 fast 和 slow 会相遇
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *slow=head,*fast=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast) return true;
}
return false;
}
};
执行用时 | 内存消耗 |
---|---|
8 ms | 9.9 MB |
set集合大小变化(一样看看就好)
- 利用集合的性质,去重
- 若有环,就会重复插入相同的节点,那么set大小不会发生变化
- 若set大小没有发生变化,那么说明存在环
class Solution {
public:
bool hasCycle(ListNode *head) {
set<ListNode*> a;
ListNode *q=head;
int count=0;//记录set的大小
while(q)
{
a.insert(q);
if(count==a.size())
return true;
q=q->next;
count=a.size();
}
return false;
}
};
执行用时 | 内存消耗 |
---|---|
32 ms | 12.1 MB |