题目:
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
方法1:HashSet表:
思路:遍历结点,将结点放入HashSet中,遍历链表并查看HashSet中有无当前节点,有则返回true。
具体如下:
设置一个HashSet表,遍历链表,判断:
-
如果HashSet中没当前要遍历的结点,将该结点存放到HashSet中,继续遍历;
-
如果HashSet中有当前要遍历的结点,返回true;
-
遍历时,遇到下一个元素为null,说明后面没有结点了,返回false。
参考代码:
public static boolean hasCycle(ListNode head) {
if(head == null)return false;
Set<ListNode> listNodes = new HashSet<>();
ListNode p = head;
while(p != null){
if(listNodes.contains(p)){
return true;
}else{
listNodes.add(p);
}
p=p.next;
}
return false;
}
补充:若有环,返回环的位置
方法2:快慢指针法:
设置2个指针fast和slow,slow指向head节点,fast指向head节点,遍历链表,slow每次移动1个位置,fast每次移动2个位置,有2种情况:
-
fast追上slow,说明存在环,返回true;
-
fast.next = null,说明不存在环,返回false。
参考代码:
public static ListNode hasCycle1(ListNode head){
if(head == null ||head.next==null)return null;
ListNode slower = head;
ListNode fast = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slower = slower.next;
if(fast == slower){
fast = head;
while(fast != slower){
fast = fast.next;
slower = slower.next;
}
return slower;
}
}
//如果有环,则在while中返回,没有环,才执行到这里,所以直接返回null
return null;
}