题目
前一题【刷题1】LeetCode 141. 环形链表 java题解
题目
分析
本题思路:
设链表共有a+b个节点,链表头部到链表入口有a个节点,链表环有b个节点。
第一次相遇时,设两指针分别走了f,s步
f=2s //f走的步数时s的两倍,因为f的速度是s的两倍
f=s+nb //f比s多走了n个环的长度
可得,f=2nb,s=nb。
所有走到链表入口节点的步数是a+Nb,而目前slow走了nb,所以slow只要再走a步停下来就可以到环的入口。
但是a的值不知。构建一个指针,它和s同时走a步,s就走了a+nb步到达环的入口,与这个指针重合。哪里走到入口需要a呢,答案是从链表头部head。
龟兔赛跑算法:Floyd判圈算法 龟兔赛跑算法
更新:
一个细节:为什么判断环不用while(fast!=slow)?因为开始时,快慢指针都等于head。所以选择do while。
拓展
打印首尾节点、求出环的长度
代码
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null||head.next==null)
return null;
ListNode slow=head;
ListNode fast=head;
do{
//没有环,返回null
if(fast==null||fast.next==null)
return null;
slow=slow.next;
fast=fast.next.next;
}while(slow!=fast);//相遇,退出循环
fast=head;//快指针回到起点,慢指针不动
//同时前进且速度相同
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return fast;
}
}
复杂度
时间复杂度:O(N),其中 N 为链表中节点的数目。在最初判断快慢指针是否相遇时,slow 指针走过的距离不会超过链表的总长度;随后寻找入环点时,走过的距离也不会超过链表的总长度。因此,总的执行时间为 O(N)+O(N)=O(N)。
空间复杂度:O(1)。我们只使用了三个指针。