title: '算法:链表中环的入口结点' cover: https://img.paulzzh.com/touhou/random?58 categories: 算法题目 date: 1996-07-27 08:00:00 tags: [算法题目, 链表, 双指针]
<br/>
<!--more-->给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
快慢指针的方法;
首先快慢指针都从头开始, 快指针每次两步, 慢指针每次一步;
如果两个指针最终相遇, 则说明链表存在环!
此时快指针从当前继续向前走(每次一步), 而慢指针从链表头开始走(每次一步), 最终两个指针会相遇在入口节点;
可以通过计算两个指针的路程来证明;
简单证明一下:
设:
则:相遇时:
快指针路程=a+(b+c)k+b
k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。
慢指针路程=a+b
快指针走的路程是慢指针的两倍,所以:
(a+b)*2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c
这个式子的意思是:链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度
其中k>=1,所以为k-1>=0圈。
所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode head) {
if (head == null || head.next == null) return null;
ListNode fast = head, slow = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
// 有环
if (slow == fast) {
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
return null;
}
}