本题返回环入口的位置。使用快慢指针,快指针每次移动两个,慢指针每次移动一个。设前一段距离是a,进入环内到slow和fast相遇的地点距离是b,环内剩下的距离是c,如图所示。
环的长度是b+c
慢指针移动距离是a+b
快指针移动距离是a+b+k(b+c)
比慢指针多移动k圈,k为整数。
还有一层关系是快指针一次移动2个距离,慢指针一次移动一个,有快指针移动距离是慢指针2倍,有公式:2*(a+b) = a+b+k*(b+c)
化简得到a-c = (k-1)*(b+c)
即slow和fast相遇时,有个指针p从头节点出发,与slow同一速度。当slow移动到环的入口时,p到入口的距离时环的倍数。即当slow和fast相遇时,有个节点从start出发,必然会和slow在入口处相遇,此时可以得到入口的位置。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head; //
ListNode* slow = head;
while(fast != NULL){
if(fast->next == nullptr || fast->next->next == nullptr){
break;
}else{
fast = fast->next;
fast = fast->next;
}
slow = slow->next;
if(slow == fast){
ListNode* s = head;
while(s != slow){
s = s->next;
slow = slow->next;
}
return s;
}
}
return nullptr;
}
};
对于160题链表相交,也可以用类似思路处理。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode*p = headA;
ListNode*q = headB;
while(p != q){
p = p? p->next : headB;
q = q? q->next : headA;
}
return p;
}
};