一、环形链表
思路1:使用hash,判断是否contains就行
思路2:使用快慢指针,快慢指针相遇则存在环(照着图比划一下就发现这是肯定的,即将相遇时只有错位2格和错位1格的情况,错位1格下一次同时位移后就相遇,错位2格下一次同时位移后变成错位1格)
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
return true;
}
}
return false;
}
}
二、环形链表入口
思路:
最重要的就是弄清楚判断入口处即 a=c
(此处的z点只是个假设,b可以等于0)
假设快指针转了一圈就和慢指针在Z点相遇了:
慢指针走过的路程:a+b
快指针走过的路程:a+b+c+b
慢指针和快指针路程关系:2*(a+b)=a+b+c+b 得出a=c
即相遇之后从head以1的速度和慢指针相遇Y点就是入口
假设快指针转了n圈才和慢指针在Z点相遇了:
快指针走过的路程:a+n*(b+c)+b
慢指针走过的路程:a+b
慢指针和快指针路程关系:2*(a+b)=a+n*(b+c)+b
得出 a=(n-1)*b+n*c=(n-1)(b+c)+c
只是说明p1从head以1的速度前进,在与p2从Z点以1的速度前进,相遇之时p2多转了n-1圈
Z点也就是快慢指针相遇之点,可以用慢指针替代p2
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
while(slow != head){
slow = slow.next;
head = head.next;
}
return head;
}
}
return null;
}
}