上一篇文章咱們分析了下鏈表之反轉單向鏈表,這篇文章咱們來分析下另一個關於鏈表的經典題目。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