题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路
思路一:暴力法,用数组记录遍历过的结点,容易想到。缺点:时间复杂度为O(),需要额外的数组。
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode * res = NULL;
ListNode * p;
vector <ListNode*> arr;
p = pHead;
while(p)
{
if(!arr.empty())
{
for(int i = 0;i < arr.size() - 1; i++)
{
if(arr[i] == p)
{
res = p;
return res;
}
}
}
arr.push_back(p);
p = p->next;
}
return res;
}
思路二:(结论证明,画一个图,设各段长度,通过等式2*s_slow = s_fast化简证明)时间复杂度为。
定义两个指针,快指针fast和慢指针slow,fast每次移动两个,slow每次移动一个;
若两指针相遇,则肯定存在环;
相遇后将其中一个指针指向链表头,另一个指针指向相遇的结点,两个指针以相同的速度每次移动一个,则再次相遇点就是环的入口结点。
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return NULL;
ListNode* slow = pHead->next;
ListNode* fast = pHead->next->next;
while(fast != slow)
{
if(fast == NULL || fast->next == NULL)//无环
return NULL;
fast = fast->next->next;
slow = slow->next;
}
slow = pHead;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return fast;
}