1. 题目描述:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题思路:
1,判断是否有环,利用快慢指针,fast一次走两步,slow一次走一步,如果能够相遇则有环,且当相遇的时候 slow 一定是在环内没走完一圈,因为假设slow入环的时候fast正在环内距离入环口m的位置,这样当fast到达入环口3的时候走的路程是(m+n)对应的slow走的路程就一定是 (m+n)/2 而m一定是小于n的,所以当fast再次走到第三个入环口的时候,slow刚刚的那一圈还没有走完,所以一定是slow进环的第一圈相遇
2,找到相遇点后如何找到入环口
- 假设fast在环内走了n圈后在y点相遇
- 可以得到公式
- 2(x+y) = x + n(y+z) +y
- 化简得 x = (n-1)(y+z) + z
- 可以知道,当n = 1的时候 x = z
- 因为(y+z)就是环的结点个数 A ,进而可以理解为 x = A + z 此时就可以推断出:
- 不论n等于几,当一个指针从相遇结点,一个指针从开始结点同时出发,当他们相遇的时候就是入口结点,因为 x = z
- 参考思路出处
3. 解题代码:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//总体思想是快慢指针
ListNode *fast = head,*slow = head;
while(fast != nullptr && fast->next != nullptr){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
//相遇 x = (n-1)(y+z)+z
//这就可以得出,当n = 1 的时候,x = z
//进而可以推导出,一个结点从相遇点出发,一个指针从头节点出发,那么他们会刚好到入环点相遇
ListNode* index1 = fast;
ListNode* index2 = head;
while(index1 != index2){
index1 = index1 -> next;
index2 = index2 -> next;
}
return index1;
}
}
return nullptr;
}
};
4. tips:
如何判断链表有环:使用快慢指针,一个一次走两步,一个一次走一步,如果能相遇,则说明是有环的。