环形链表
题目描述:
给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回 true 。 否则,返回 false 。
基本想法:
在本题中我们只需判断链表存在环或者不存在环这两种情况。
从局部来看的话:
- 我们用一个指针来访问节点图形
- 用哈希表记录下每一次访问
- 通过查看哈希表中记录的元素来判断是否为环形
具体实现代码如下:
class Solution:
def hasCycle(self, head: ListNode) -> bool:
seen = set()
while head:
if head in seen:
return True
seen.add(head)
head = head.next
return False
性能分析:时间复杂度为N,空间复杂度为N
当然我们还有一种更为精巧的办法:
我们可以采用快指针和慢指针的方式:
- 在访问节点时我们用两个指针来进行同时访问
- 但一个走得快一个走得慢
- 一直访问下去,如果访问到链表尾部就返回
- 一旦链表有环,由于两个指针的速度不一样,就会出现慢的被超圈的现象,这是两个指针所指的对象为同一个。
具体实现代码如下:
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow = fast = head # 乌龟和兔子同时从起点出发
while fast and fast.next:
slow = slow.next # 乌龟走一步
fast = fast.next.next # 兔子走两步
if fast is slow: # 兔子追上乌龟(套圈),说明有环
return True
return False # 访问到了链表末尾,无环
性能分析:时间复杂度为N,空间复杂度为1