题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:快慢指针追及问题
设置一个快指针,每次走两步
设置一个慢指针,每次走一步
如果有环,那么这俩指针终会相遇
如果没环,那么快指针一定会走到空
假设环的长度为S环
快指针走过的长度为S快
慢指针走过的长度为S慢
当它们相遇时,快指针一定是比慢指针多了n圈(n>=1)
那么
① S环 * n + S慢 = S快
因为快指针每次走两步,慢指针每次走一步
所以
② S快 = 2 * S慢
联立①②式
得
③ n * S环 = S慢
假设相遇点距离环的入口长度为S
由③得:④ n * S环 + S = S慢 + S
④式的意思就是:左式从相遇点的角度出发,右式从链表头结点的角度出发,当
在相遇点和链表头结点同时同速出发,那么一定会在环的入口处相遇
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode *quick = pHead, *slow = pHead;//快慢指针
while(quick && quick->next){ //因为每次走两步所以next也要判断是否为空
quick = quick->next->next;
slow = slow->next;
if(quick == slow) break;
}
if(!quick || !quick->next) return NULL;//没环
slow = pHead; //这时slow从头再走,quick在相遇点与slow同速走
while(slow != quick){
quick = quick->next;
slow = slow->next;
}
return slow;
}
};