Problem:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.Explanation:
给定一个链表,判断是否有环,若有环则返回环的开始结点。
My Thinking:
基于Linked List Cycle I的思路1,添加返回值即可。
My Solution:
public class Solution {
public ListNode detectCycle(ListNode head) {
Set<ListNode> nodes=new HashSet<>();
while(head!=null && head.next!=null){
if(nodes.contains(head.next)){
return head.next;
}else{
nodes.add(head);
head=head.next;
}
}
return null;
}
}
Optimum Thinking:
基于Linked List Cycle I的思路2,见下图:
第一次相遇时,快指针一定经过了a+b+c+1+b这个路线,慢指针则经过了a+b的路线,两个指针在M点相遇。由于我们知道快指针的速度是慢指针的2倍,那么在相同时间内,快指针的路程也是慢指针的2倍,就有a+b+c+1+b=2(a+b),化简后得到a=c+1,即从链表起点到环起点的距离=相遇点到环起点的距离。
那么我们得到相遇点之后,重新设定两个速度相同的指针,一个从链表起点开始走,一个从相遇点开始往后走,那么经过相同的移动次数,就一定相遇在环的起点。
Optimum Solution:
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
ListNode meet=null;
boolean flag=false;
//先通过快慢指针找到第一次相遇点
while(fast!=null && fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
meet=slow;
flag=true;
break;
}
}
//如果没有相遇则返回null
if(flag==false)
return null;
//设置两个相同速度的指针,相遇时返回交点。
slow=head;
fast=meet;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return slow;
}
}