图示
-
一般而言的单链表的尾部结点的next域指向null,是没有环的;
-
当单链表的尾部结点的next域指向其前面任一结点时,则证明链表有环。
思路分析
- 定义两个指针,快指针和慢指针,快指针步长为2,慢指针步长为1。
- 如果链表有环,则两个指针一定可以在环内相遇(为什么?可以很明确的一点是,如果链表没有环,两个指针永远不会相遇。接下来只需要证明在有环的情况下,两个指针一定会相遇,证明见图解2)
- 图解
-
特例
-
两指针一定会相遇的证明
以fast为起点,把环想象成一个无限延伸的直线,问题转换为直线距离的追及问题,直到fast追上slow为止。
① 假设fast和slow相距x,fast速度为2,slow速度为1,时间t后,两者相遇
则一定有t+x = 2t => x = t,换言之就是,两者相距x,再移动x次就追上了
② 再回到环,一定有 x属于[0,L),所以经过有限次移动一定可以相遇
代码实现
public static boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}