给定一个链表,判断链表中是否有环。

 

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

示例 1:

LeetCode141.环形链表_链表

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

import java.util.HashSet;
import java.util.Set;

/**
* @author mac
* @date 2020/11/7-11:45
*/
public class t141_环形链表 {
/**
* Definition for singly-linked list.
*/
class ListNode {
int val;
ListNode next;

ListNode(int x) {
val = x;
next = null;
}
}

/**
* 哈希表,时间复杂度O(n),空间复杂度O(n)
*/
public boolean hasCycle0(ListNode head) {
if (head == null || head.next != null) {
return false;
}
// 创建Hash表(无序不可重复的特点)
Set<ListNode> seen = new HashSet<ListNode>();
// 如果不为空,证明还没循环完
while (head != null) {
// 有重复的
if (!seen.add(head)) {
return true;
}
// 遍历下一个节点
head = head.next;
}
// 全部放一遍没有重复的
return false;
}

/**
* 快慢指针,时间复杂度O(n),空间复杂度O(1)
*
* @param head
* @return
*/
public boolean hasCycle(ListNode head) {
// 头结点不为null,或者头结点的下一个节点不为null,防止只有一个节点,后续报空指针
if (head == null || head.next == null) {
return false;
}
// 设置快慢指针
ListNode i = head;
// 从头结点的下一位开始,一前一后遍历链表
ListNode j = i.next;
// 如果j追赶上i
while (i != j) {
// 只有一位j就是空的,或者j的后面没有元素了,返回false
if (j == null || j.next == null) {
return false;
}
// i指针走一步
i = i.next;
// j指针走两步
j = j.next.next;
}
// i=j的情况,证明具有环形链表
return true;
}
}