一、判断链表的中点
代码:
/**
* 判断链表的中点
* 通过两个指针:一个快指针、一个慢指针。
* 快指针走的速度是慢指针的2倍,那么当快指针走到链表的尾部,慢指针走的当然是快指针的一半那也就是链表的中点了。
*
* @param head 头结点
* @return middleNode
*/
private static Node findMiddleNode(Node head){
// 需要两个指针:一个快指针、一个慢指针,快指针的速度是慢指针的2倍
Node slow=head,fast=head;
while (fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
二、判断链表是否有环并找到环的入口
将问题分为两部分:
-
判断链表是否有环
需要两个指针:一个快指针、一个慢指针,快指针走的速度是慢指针的2倍,如果两个指针相遇,那么就证明链表有环。
-
找到链表中环的入口
因为快指针走的速度是慢指针的2倍,copy一下图片来看一个公式:
这时,我们只需要让一个指针【temp】从head开始走,同时slow也开始走,两个指针相遇的节点,就是链表中环的入口。
代码:
/**
* 判断链表是否有环,有环的话寻找环的入口
* 1. 判断链表是否有环:
* 需要两个指针【一个快指针(fast)、一个慢指针(slow),快指针走的速度是慢指针的2倍】
* 如果fast与slow相遇,证明链表有环。
* 2. 寻找环的入口:
* 可以通过计算得出:slow当前所在位置-环入口的距离==head-环的入口的距离
* 所以让一个指针【temp】从head开始走,同时slow也走
* temp和slow总有相遇的时候,相遇时指向的节点就是环的入口
*
* @param head 头结点
* @return 环的入口节点
*/
private static Node findCycleAndEntry(Node head){
// 需要两个指针来判断链表是否有环:一个快指针、一个慢指针,规定快指针走的速度是慢指针的2倍
// 如果快指针与慢指针相遇那就证明链表有环:快指针走的是慢指针走的距离的2倍
Node slow=head,fast=head;
while (fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if (slow==fast){
// 快慢指针相遇:证明链表有环
// 寻找环的入口:需要一个指针temp,这个指针指向head
// temp和slow每次都走一步,相遇点就是环的入口(因为 距离【fast】==2*距离【slow】,通过这个等式我们就能判断,距离【head-入口】==距离【slow-入口】)
Node temp=head;
while (temp!=slow){
temp=temp.next;
slow=slow.next;
}
return slow; // 返回环的入口
}
}
return null; // 链表没有环:返回null
}