描述
判断给定的链表中是否有环。如果有否则返回true,否则返回false。
数据范围:链表长度 0≤n≤10000,链表中任意节点的值满足 ∣val∣<=100000
要求:空间复杂度 O(1),时间复杂度 O(n)。
例如输入{3,2,0,-4}时,对应的链表结构如下图所示:
可以看出环的入口结点为从头结点开始的第1个结点(注:头结点为第0个结点),所以输出true。
结构体初始定义如下:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
解法一 哈希表
1.set哈希表
class Solution
{
public:
bool hasCycle(ListNode *head)
{
set<ListNode*> s;
while(head!=NULL)
{
if(s.find(head)!=s.end())
return true;
else
s.insert(head);
head=head->next;
}
return false;
}
};
2.map哈希表
class Solution
{
public:
bool hasCycle(ListNode *head)
{
map<ListNode*,bool> m;
while(head!=NULL)
{
if(m.find(head)!=m.end())
return true;
else
m[head]=true;//添加键值
head=head->next;
}
return false;
}
};
以上两种方法在本质上是一样的。都是利用哈希表来判断链表中是否有环。
解法二 快慢双指针
使用两个指针,fast和slow,他们起始的位置都是链表头部,随后,slow指针每次向后移动一个位置,而fast每次向后移动两个位置,如果链表中存在环,那么这两个指针最终会再次相遇。
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;
}
};
解法三 灵魂解法。。(不推荐)
题目中说了n的范围是0到10000,所以如果循环次数大于10000是不是说明一定有环,反之如果循环到一定次数结束了说明一定无环...
class Solution {
public:
bool hasCycle(ListNode *head) {
int sum=0;//题目中说了n的范围是0到10000,所以如果循环次数大于10000是不是说明一定有环,反之如果循环到一定次数结束了说明一定无环
while(head)
{
head=head->next;
sum++;
if(sum>10000)
return true;
}
return false;
}
};