LeetCode.142 环形链表2 (Medium)
这里分享一个LeetCode上的:图解,非常便于理解。
该题是基于环形链表:判断是否有环,并找到环的具体位置(返回环开始的节点)。同时本题需要一点数学和图像上的推导,来证明某一个点就是环起始的位置。
第一步和环形链表一样,先通过快慢指针判断是否有环,并找到快慢指针相遇的位置。
此时假设:慢指针走了k
步。则:快指针走了2k
步,快指针走过的距离减去慢指针走过的距离是k
步,即为环周长的整数倍。
此时假设:快慢指针相遇点距离环起始位置的距离m
,则从head
到环起始点的距离为k-m
。
此时快指针走到环起始点的距离也为k-m
,这里并未限定是从相遇点到起始点的最短路径,因为已经考虑到了套圈的可能性。因而只需让快指针和慢指针以相同的速度(每次前进1个节点),并且slow重新从head开始,都走k-m
的距离,即可相遇,相遇的点即为环的起点。
public class Solution {
// 题目要求,返回环的位置
public ListNode detectCycle(ListNode head) {
// 还是快慢指针那一套,先确定有没有环
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) break; // 相遇,有环
}
// 确定是:1.有环break 2.没环while结束
if (fast == null || fast.next == null) return null;
// 排除无环情况
// 假设此时,slow指针走了k步到达相遇点,则fast指针走了2k步
// fast - slow走过的距离 = 2k - k = k,即为环的周长的n倍(n >= 1);k = 环周长的整数倍
// 假设相遇点距离环开始的地方的距离为m(劣弧距离)
// 则head到环起点的距离为 k - m
// 此时让slow重新回到head,fast和slow以相同的速度前进,当他们都前进k-m的距离时即会相遇,这个地方就是环的起点位置
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}