前言
对于环问题,快慢指针是一种常用的手段。一步两步走,通过判定是否相遇来判定是否存在环。而且快慢指针还能轻松的求到入环点。
一、环形链表
二、快慢指针
1、相遇即有环
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/*
对于环问题,可采用快慢指针进行判定。
快慢指针:慢指针走一步,快指针走两步,有环则两者相等,无环则快指针先到null。
*/
public boolean hasCycle(ListNode head) {
if(null == head) return false;
ListNode slow = head,fast = head.next;
while(slow != fast && fast != null){
slow = slow.next;
fast = fast.next;
if(fast != null) fast = fast.next;
}
return fast == slow;
}
// 如果存在环,求入环节点怎么办?
/*
设起点到入环点的距离为a;设入环点到相遇点的距离为b;
由于快指针是慢指针的2倍,所以除了快指针走的a+b,还剩a + b = k * L(L为环的长度,k为常数。);
从环点走到相遇点,已经走了b了,再走距离为a时,共走了a+b=kL,则走了k圈回到起点。
而起点到环点的距离也为a,所以从起点走到环点时,快指针也经走了k圈回到环点,两者相遇,得到环点。
*/
}
2、入环点
设起点到入环点的距离为a;设入环点到相遇点的距离为b;
由于快指针是慢指针的2倍,所以除了快指针走的a+b,还剩a + b = k * L(L为环的长度,k为常数。);
从环点走到相遇点,已经走了b了,再走距离为a时,共走了a+b=kL,则走了k圈回到起点。
而起点到环点的距离也为a,所以从起点走到环点时,快指针也经走了k圈回到环点,两者相遇,得到入环点。
总结
1)对于环问题,可采用快慢指针的相遇来判定是否存在环。
2)快慢指针不仅用于判定环,在对链表进行归并排序时,还可以取到链表的中点。
3)对于环入口问题,可再从起点行走,再次和快指针相遇时,则是入环点。
参考文献
[1] LeetCode 环形链表