题目要求
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?
这道题目要求判断一个链表中是否有环,如果有环,就返回环中的第一个节点。
判断是否有环
判断是否有环有两种方法,第一种是双指针的方法,双指针方法意味着快指针一定有一天会遇上慢指针,只要链表中有环。
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;
}
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。