Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note: Do not modify the linked list. Follow up: Can you solve it without using extra space?
這道題目要求判斷一個鏈表中是否有環,若是有環,就返回環中的第一個節點。node
判斷是否有環有兩種方法,第一種是雙指針的方法,雙指針方法意味着快指針必定有一天會趕上慢指針,只要鏈表中有環。面試
public boolean hasCycle(ListNode head) { if(head==null) return false; ListNode walker = head, runner = head; while(runner.next!=null && runner.next.next!=null){ walker = walker.next; runner = runner.next.next; if(walker==runner) return true; } return false; }
還有一種方法是指將鏈表的結果給拆掉,一旦遍歷過當前節點,就將當前節點的下一個指針指向dummy節點。若是有環,就會重複遇到這個指向dummy的節點。則該鏈表有環,且該節點就是環的起始節點。可是這個方法會毀壞原來鏈表的數據結構。微信
public boolean hasCycle2(ListNode head){ if(head==null) return false; ListNode dummy = new ListNode(0); while(head.next!=null){ if(head.next==dummy)return true; ListNode temp = head.next; head.next = dummy; head = temp; } return false; }
那麼如何才能在環中找到起始節點呢?這就要找出雙指針之間運動的規律了。當快慢指針第一次相遇時,咱們假設慢指針和環中第一個節點距離爲X,而環中第一個節點距離起始節點爲Y。而由於快指針在走了一圈之後也停留在該節點,所以快指針走過的總距離爲(X+Y)*2。又由於快慢指針相遇決定了快指針比慢指針多走了一圈,所以2(X+Y)-(X+Y)=CYCLE,也就是X+Y=CYCLE。這時咱們能夠知道若是再走Y步,慢指針就能夠回到環中的第一個節點,而Y也剛好是環中第一個節點距離起始節點的位置。
所以若是這時有另外一個指針同時從起點出發,則兩者相遇的地方就是環的起始節點。數據結構
public ListNode detectCycle(ListNode head) { if(head==null) return null; ListNode runner = head, walker = head; while(runner.next!=null && runner.next.next!=null){ walker = walker.next; runner = runner.next.next; if(walker==runner){ ListNode temp = head; while(temp!=walker){ temp = temp.next; walker = walker.next; } return temp; } } return null; }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~spa