环路检测
题目来源:https://leetcode-cn.com/problems/linked-list-cycle-lcci/
1. 题目
给定一个有环链表,实现一个算法返回环路的开头节点。
有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路。
2. 示例
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
3. 题解+code
快慢指针
解题思路:
如果链表内成环,则速度不同的指针一定会在环内相遇,相遇点不一定是环的起点
假设快慢指针在B点相遇
相遇时指针fast路程s1=T+M+xS(x是fast在环内循环的次数)
相遇时指针slow路程s2=T+M
s1和s2有:s1=2 s2
整理得:T = (S-M) + (x-1)S
即: T = N + (x-1)S
此时让fast指针回归链表起点,双指针同速前进
当fast指针至A点时,路程为T,slow也走了T,由3可知:
此时,fast和slow恰好都在环路起点
/**
* 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) {
if(!head||!head->next)
{
return NULL;
}
ListNode *fast = head,*slow = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
if(slow == fast)
break;
}
//没有环路,返回NULL
if(fast != slow){
return NULL;
}
//寻找环的起点
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
};