原题地址(简单)
方法1—双指针
思路
此题是Floyd龟兔赛跑算法的典型应用,使用龟兔赛跑算法的第一阶段即可解决。
强烈建议您看一下本文,看完后不仅能拿下本题,还可以进一步拿下环形链表II。
也就是快慢指针,慢指针一次一步,快指针一次两步,如果有环,则一定相遇
python代码
def hasCycle(self, head: ListNode) -> bool:
fast = slow = head
while fast and slow:
if fast.next:
fast = fast.next.next
else:
return False
slow = slow.next
if fast == slow:
return True
return False
时间复杂度O(n)
- 如果无环,快指针走到头,就是O(n)
- 如果有环
- 假设环前有n个元素,环中有m个元素,当慢指针走到环的起点时(走了n步),这时快指针除了在环前走的n步,还在环内走了n步。
- 如果给环中元素按起点顺时针顺序标号(起点为0号,依次为1,2,3,….,m-1号),则此时快指针在环内的
n mod m
号元素上,我们记为第k号元素,而慢指针在第0号元素上。 - 慢指针在第0号元素,快指针在第k号元素,快指针比慢指针走的快,由于是个环,所以可以看成慢指针在快指针前面,并且领先
m-k
步。 - 慢指针领先快指针
m-k
步,由于快指针速度是慢指针两倍,所以轻易得知,经过m-k
次迭代,也就是说慢指针走了m-k
步,快指针走了2(m-k)
步,两者相遇。 - 而这个
m-k
,由于是环中的部分长度,所以一定小于n,所以时间为O(n+(m-k)),也就是O(n)
空间复杂度O(1)
方法2—哈希表
思路
遍历这个链表,将遍历到的元素依次扔到哈希表里,每次先判断哈希表有无该元素。
如果存在循环,一定能找到一个元素,哈希表中已经存在,直接break,结束;
如果不存在循环,遍历完毕,直接返回False
注意:哈希表中存的是节点,而不是节点值。如果存节点值,无法解决[1,2,2,3]这样的情况
cpp代码
bool hasCycle(ListNode *head) {
set<ListNode*> s;
ListNode *p=head;
while(p)
{
if(s.find(p)!=s.end()) return true;
else s.insert(p);
p = p->next;
}
return false;
}
python代码
def hasCycle(self, head: ListNode) -> bool:
p = head
shash = set([])
while p:
if p in shash:
return True
shash.add(p)
p = p.next
return False