标签:复杂度 solution 链表是否有环 ast false fas auto math pre
题目描述
快慢指针:若链表有环,则两指针必在将来某一时刻相遇:
假设环的长度为\(L\),快指针距离环的入口距离为\(S\),慢指针在入口,则经过\(t\)时间相遇,有:
\(S+2t-t=nL\),即:\(S+t=nL\),又\(S<L\),故取\(n=1, t=L-S\),即慢指针在一圈内必能遇到快指针。
//单链表定义
struct ListNode{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL) {}
};
class Solution {
public:
bool hasCycle(ListNode* head)
{
if (head == NULL)
return false;
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
return true;
}
return false;
}
};
题目描述
设链头距离环的入口距离为\(s_1\),相遇点距离入口距离为\(s_2\),环的长度为\(L\),则快慢指针走过的路程是2倍关系:
\[2(s_1+s_2)=nL+s_1+s_2\]
相遇前快指针已经绕了\(n\)圈,化简:
\[s_1=nL-s_2\]
1,\(n=1\),则\(s_1=L-s_2\);
2,\(n>1\),则\(s_1=L-s_2+(n-1)L\)。
也就是说:设两个指针\(p_1, p_2\),\(p_1\)指向链头,\(p_2\)指向相遇点,每次都走一步,则两指针必在环的入口相遇。
//单链表定义
struct ListNode{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL) {}
};
class Solution{
public:
ListNode* detectCycle(ListNode* head)
{
auto fast = head;
auto slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
break;
}
if(!fast || !fast->next) //无环,fast走到尽头
return nullptr;
slow = head; //一个指向链头,另一个指向相遇点
while(slow != fast)
{
fast = fast->next;
slow = slow->next;
}
return slow; //找到入口
}
};
标签:复杂度 solution 链表是否有环 ast false fas auto math pre
原文地址:https://www.cnblogs.com/EIMadrigal/p/12130815.html