一个链表中包含环,请找出该链表的环的入口结点。
断链法
时间复杂度为O(n)
两个指针,一个在前面,另一个紧邻着这个指针,在后面。
两个指针同时向前移动,每移动一次,前面的指针的next指向NULL。
也就是说:访问过的节点都断开,最后到达的那个节点一定是尾节点的下一个,
也就是循环的第一个。
这时候已经是第二次访问循环的第一节点了,第一次访问的时候我们已经让它指向了NULL,
所以到这结束。
但是这种方法修改了链表的指向
class Solution
{
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if (pHead == NULL
|| pHead->next == NULL)
{
return NULL;
}
ListNode* previous = pHead;
ListNode* current = pHead->next;
while (current != NULL)
{
previous->next = NULL;
previous = current;
current = current->next;
}
return previous;
}
};
快慢指针法
如果存在环,找到环的起始结点
当fast指针等于slow指针时,slow指针肯定还没有遍历完整个链表,而此时fast指针已经在环内循环了n圈(n>=1),假定从链表头指针开始slow走了s步,则fast走了2s步,fast所走的步数还等于s加上fast指针比slow指针在环内多走的n圈。设环长为r,则:
2s = s + nr;
=>s = nr;
设整个链表长度为L,环的入口结点到相遇结点的距离为x, 起点到环的入口结点的距离为a.
a + x = nr;
=> a + x = (n-1)r + L - a;
=> a = (n-1)r + (L - a - x);
=> 由链表的头结点到环入口结点的距离等于n-1圈环的长度+相遇点到环入口结点的距离,于是,当我们在链表头部和相遇处分别设一指针,每次各走一步,则两指针必定相遇,且相遇的第一个结点即为环的入口结点
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(!pHead || !pHead->next) return NULL;
ListNode* fast = pHead;
ListNode* slow = pHead;
while(fast && slow){
slow =slow->next;
fast = fast->next->next;
if(slow == fast)
break;
}
slow = pHead;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
链接:https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4
来源:牛客网
class Solution
{
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL)
return NULL;
ListNode* pNode = pHead;
vector<ListNode*> count; //记录节点
while(pNode)
{
//如果当前节点非空
count.push_back(pNode);
pNode = pNode->next;
//判断下一个节点是否已经访问过
if(find(count.begin(),count.end(),pNode) != count.end())
return pNode;
}
return NULL;
}
};
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL)return NULL;
vector<ListNode*> visited;
ListNode *p = pHead;
while(p)
{
auto it = find(visited.begin(), visited.end(),p);
if(it != visited.end() && p == *it)return p;
visited.push_back(p);
p = p -> next;
}
return NULL;
}
};
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL )return NULL;
vector<ListNode*> v;
ListNode *p = pHead;
while(p && (count(v.begin(),v.end(),p) == 0))
{
v.push_back(p);
p = p -> next;
}
return p;
}
};