问题描述
Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos
which represents the position (0-indexed) in the linked list where tail connects to. If pos
is -1
, then there is no cycle in the linked list.
Follow up:
Can you solve it using O(1) (i.e. constant) memory?
给定一个链表,判断它是否有一个循环。
为了在给定的链表中表示一个循环,我们使用一个整数pos来表示tail连接到的链表中的位置(0索引)。如果pos是-1,那么链表中就没有循环。
跟进:
你能用O(1)(即常数)内存来解决它吗?
输入: head = [3,2,0,-4], pos = 1 输出: true
输入: head = [1,2], pos = 0 输出: true
输入: head = [1], pos = -1 输出: false
Python 实现
要判断一个链表是否存在环,一种比较常用方法是定义两个指针,一个走快点,一个走慢点,只要在某个时候,两个指针重合了,说明链表存在环。严谨一点的描述是,我们可以定义两个指针,一个每次只走一步,另一个一次走两步,在指针没有指向空,也就是没有到达链表末尾前,出现两个指针重合的情况,说明这个链表存在环。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
oneStep = head
twoStep = head
while twoStep != None and twoStep.next != None:
oneStep = oneStep.next
twoStep = twoStep.next.next
if twoStep != None and twoStep == oneStep:
return True
return False
可能有人看完代码之后,会想如果前面的那个指针把步伐设置更大,是不是就能更快使得两个指针重合,减少循环次数以节省时时间?这个想法有一定的道理,但是由于链表的长度是未知的,有可能当我们把移动更快的那个指针的步伐设置过大,即便链表存在环,这个指针每次都与另一个指针错过,这样子可能会导致更大的时间成本,甚至会错过重合的机会,导致判断错误。当然,指针步长的设置可以很有技巧,但讨论起来就比较复杂了。以后有机会再深入探讨一下。