力扣HOT100之链表:142. 环形链表 II
这道题已经刷过3回了,还好还记得思路,直接一遍过,说下主要的思路。
首先要判断一个链表是否有环,我们就需要定义快慢指针进行判断,在起始阶段,快慢指针都指向链表的头节点,然后进行循环,当快指针fast
及fast -> next
不为空时循环继续,若循环退出,就说明链表中没有环,直接返回nullptr
,若在循环内出现了快慢指针相遇的情况,则说明链表内有环,我们进行下一步分析,如下图所示。
假设从链表头节点到环的入口的距离为x
,从入口到快慢指针相遇处(沿前进方向)的距离为y
,从快慢指针相遇处到环的入口(沿前进方向)的距离为z
,当快慢指针相遇时,慢指针在环内一定没走完一圈(详细证明可以看我的这篇博客),则快慢指针的路程关系为2倍的关系,根据上面的性质我们可以得到一个原始的等式,然后经过一步步化简可以得到划红线的结果,其重要性质已经用红字写出,根据上面的性质,我们可以新定义一个慢指针result
,从链表头节点出发,每次只移动一个节点,而慢指针slow
同时继续向前进,当slow
和result
相遇时,slow
走的路程为z+(n - 1)(y + z)
(n - 1圈+z),而result
走了x
,当二者相遇时,相遇处就是入口,直接返回即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast -> next){
fast = fast -> next -> next; //快指针走两步
slow = slow -> next; //慢指针走一步
if(fast == slow){ //链表有环且在环内相遇
ListNode* result = head;
while(result != slow){
result = result -> next;
slow = slow -> next;
}
return result;
}
}
return nullptr; //链表无环
}
};