题目
给定一个链表,判断链表中是否有环
为了表示给定链表中的环,我们使用整数pos
来表示链表尾连接到链表中的位置(索引从0
开始)。 如果pos
是-1
,则在该链表中没有环
示例:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
解法
这里给这道题提供两种解法
使用 Set
检测一个链表中是否存在环,可以理解为检测链表中存不存在一个节点,这个节点有两个指针同时指向它,这样链表中就产生了环,我们可以使用 Set 来解决这个问题
我们从头至尾遍历这个链表,每到一个节点,就检测实现定义好的 Set 中是否存在一个相同的节点,不存在就将它放入 Set,反之如果存在,就说明这个节点被两个节点同时所指向,使链表形成了环
Java 代码
public boolean hasCycle(ListNode head) {
if (head == null)
return false;
Set<ListNode> set = new HashSet<ListNode>();
while (head.next != null) {
head = head.next;
if (set.contains(head))
return true;
else
set.add(head);
}
return false;
}
使用快慢指针
另一种方法是使用快慢指针,即定义两个指针,都从链表的头部开始遍历,只要保证慢指针每次走的步数小于快指针即可(通常就慢指针一次走一个节点,快指针一次走两个就行),当其中一个指针为空了,就说明链表到头了,没有环,而如果两个指针相遇了,就说明链表是有环的
这个解法的原理就是,如果链表没有环,快慢指针永远都不会相遇
Java 代码
public boolean hasCycle(ListNode head) {
ListNode fast = head, slow = head;
while (fast != null && slow != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast)
return true;
}
return false;
}
Python 代码
def hasCycle(self, head: ListNode) -> bool:
fast = slow = head
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False