上一篇文章咱们分析了下链表之反转单向链表,这篇文章咱们来分析下另一个关于链表的经典题目。java
判断链表是否有环(在leetcode上的题目地址:环形链表)segmentfault
给定一个链表,判断链表中是否有环spa
1、能够使用hash表来实现,遍历链表,每一个节点放入hash表中,若是hash表中包含了某个节点,那么说明有重复节点存在,便是有环。若是没环,那么链表会遍历结束。代码以下:指针
public static <T extends Comparable<T>> boolean hasCycle1(Node<T> head) { HashSet<Node<T>> set = new HashSet<>(); for(Node<T> n=head;n!=null;n=n.getNext()) { if(set.contains(n)) { return true; } set.add(n); } return false; }
复杂度分析,假设链表长度为ncode
2、上面这种方法能够解决,可是须要借助额外的空间复杂度,可否不使用额外空间解决此题呢?答案是有的,使用快慢指针,想象下,两我的在一个环形跑道上赛跑,跑得快的必定会追上跑的慢的那我的吧。下面用图示来展现下整个过程。leetcode
初始化时:rem
fast指针走两步,slow指针走一步,不停遍历的变化:get
最后快慢指针又相遇了,循环结束,代码实现以下:hash
public static <T extends Comparable<T>> boolean hasCycle(Node<T> head) { if(head == null || head.getNext() == null) { return false; } Node<T> slow = head; Node<T> fast = head; while(fast != null && fast.getNext() != null) { slow = slow.getNext(); fast = fast.getNext().getNext(); if(slow == fast) { return true; } } return false; }
复杂度分析,假设链表长度为nit