来源于http://blog.jobbole.com/106227/
给定一个链表,判断链表中是否有环。
进阶:
你能否不使用额外空间解决此题?
解法1:检查每个节点与前面所有节点中某个节点相等,若相等,则说明链表有环,否则比较下一个直至遍历完所有节点。
时间复杂度o(n^2),空间复杂度o(1)(没有用到额外空间)
解法2:创建一个以节点ID为键的Set集合,用来存储曾经遍历过的节点。然后同样是从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就用新节点和Set集合当中存储的节点作比较,如果发现Set当中存在相同节点ID,则说明链表有环。
时间复杂度o(n),空间复杂度o(n)。
#include<cstdlib>
#include<set>
#include<iterator>
class Solution {
public:
bool hasCycle(ListNode *head) {
set<ListNode *> myset;
set<ListNode *>::iterator pos;
ListNode *node = head;
while(node != NULL)
{
pos = myset.find(node);
if(pos != myset.end())
{
return true;
}
else
{
myset.insert(node);
node = node->next;
}
}
return false;
}
};
解法3:不使用额外空间,设置两个指针p1,p2,开始均指向头结点,然后每次p1向后移动一个节点,p2向后移动两个节点。然后比较两个指针指向的节点是否相同。如果相同,则判断出链表有环,如果不同,则继续下一次循环。有“环”自会“重逢”。
此方法也可以用一个更生动的例子来形容:在一个环形跑道上,两个运动员在同一地点起跑,一个运动员速度快,一个运动员速度慢。当两人跑了一段时间,速度快的运动员必然会从速度慢的运动员身后再次追上并超过,原因很简单,因为跑道是环形的。
#include<cstdlib>
#include<set>
#include<iterator>
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head == NULL)
return false;
ListNode *p1,*p2;
p1 = p2 = head;
while(p2->next != NULL && p2->next->next != NULL)
{
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2)
{
return true;
break;
}
}
return false;
}
};
运行出现下面的错误,代码复制到LeetCode官网上运行,报错:member......... 我就知道肯定又是关于NULL没弄对,第20行脑袋短路写成 || 了(上面代码已经更正了)。
AC,效率提高!。