这两道题也用到了快慢指针,前一题只要单链表判断是否有圈,第二题找出圈的起点。
前一题设置两个快慢指针,如果有圈就会相遇,相遇了就返回true,否则返回false。
第二题先做前一题一样的判断,把相遇点返回,下面做一个理论推理, 链表的总长度为L(忽略圈的存在),圈之前的长度为X,设第一个指针的速度为1,第二个指针速度为2,设第一次相遇的时间点为T(开始为0),那么第一个相遇点距离头结点的距离是1*T,此时快指针走过的总路程为2*T,他们的路程差为1*T,也就是圈的周长为T,也就是说,X+T=L,此时从相遇点到圈入口的距离为L-T=X,所以此时再分别从头和相遇点出发两个速度为1的指针,会在入口相遇。
下面是代码:
第一题:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode quick = head;
boolean flag = false;
while(slow != null && quick != null && quick.next != null && flag == false){
slow = slow.next;
quick = quick.next.next;
if(slow == quick)
{
flag = true;
}
}
return flag;
}
}
第二题:
public ListNode hasCycle(ListNode head) {
ListNode slow = head;
ListNode quick = head;
boolean flag = false;
while(slow != null && quick != null && quick.next != null && flag == false){
slow = slow.next;
quick = quick.next.next;
if(slow == quick)
{
flag = true;
}
}
if(flag == false)return null;
else
return slow;
}
public ListNode detectCycle(ListNode head) {
ListNode start = head;
ListNode point = hasCycle(head);
while(point != null && start != null)
{
if(point == start)break;
point = point.next;
start = start.next;
}
return point;
}