题目描述
-
给定一个链表,判断链表中是否有环。
-
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
-
如果链表中存在环,则返回 true 。 否则,返回 false 。
解法一:哈希表
- 思路:借助哈希表是很常用的方法,尤其是在判断是否重复访问一个数据的时候。
- 每次访问到一个节点,判断哈希表中是否存在,不存在加入,存在即说明有环。
- 遍历到node.next==null,说明无环。
public boolean hasCycle(ListNode head) {
HashSet<ListNode> hashSet = new HashSet<>();
while(head!=null){
if(!hashSet.add(head)){
return true;
}
head=head.next;
}
return false;
}
时间复杂度:O(n)
空间复杂度:O(n)
解法二:快慢指针(双指针)
- 思路:设置两个指针,分别为每次指向后一个和后两个,如果存在环,两个指针会相遇
- 首先设置快慢指针时,需要判断head.next==null,即要保证快指针不出现空指针异常,每次快指针进行移动时,需要判断移动后的节点是否为null,若为null,说明不存在环。
- 进行判断时,注释起来的代码相对更好理解,为先排除空指针异常,再进行是否相遇(即有环)的判断。
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while(slow!=fast){
if(fast==null||fast.next==null){
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
/*
while(fast!=null&&fast.next!=null){
if(fast==slow){
return true;
}
slow = slow.next;
fast = fast.next.next;
}
return false;
*/
}
}