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