满难度系数
* * * * *
,此题难度系数* * *
。
满考频热度* * * * *
,此题热度* * * * *
。
1. 题目描述
2. 题目链接
- 牛客题目链接链表中环的入口结点
3. 题目剖析
- 先判断链表中是否有环,没有则就没有入口结点,直接返回null。是否有环link
- 如果链表中有环,遍历时不会走到nullptr,定义一个fast指针和slow指针。
当fast和slow进环以就会围着环同时运动,且fast比slow每次多走一步。直到fast和slow相遇
。 - 相遇的点肯定是环里面,然后定义一个count,在定义一个结点
RmNode
从相遇结点的下一个结点开始,每走一步count++,再走到这个结点时,count就是这个环里面有多少个结点
。 - 再定义两个结点Rnode1,Rnode2都从头开始,
让Rnode1先走count步
。 再让Rnode1,Rnode2同时走
,相遇点就是环的入口结点。
3.1剖析图示
3.2 图示详解
- 先让快慢指针在环中相遇。
图一
。 - 从相遇点的下一个开始,计算环里面有几个结点。
图二
。 - 定义两个结点都从头开始,让一个结点先走环里面的节点数,然后两个环在同时走。
图三
。
4. 解题代码
/**
* 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) {
//注释1
if(head == nullptr || head->next == nullptr)
{
return nullptr;
}
//注释2
ListNode *fast = head;
ListNode *slow = head;
ListNode *point = nullptr;
int count = 1;
ListNode *RmNode = nullptr;
while(fast && fast->next)
{
fast = fast -> next -> next;
slow = slow -> next;
if(fast == slow)
{
point = fast;
break;
}
}
//注释3
if(point == nullptr)
{
return nullptr;
}
//注释4
RmNode = point->next;
while(RmNode != point)
{
count++;
RmNode = RmNode -> next;
}
//注释5
ListNode *Rnode1 = head;
ListNode *Rnode2 = head;
while(count)
{
Rnode1 = Rnode1 -> next;
count--;
}
//注释6
while(1)
{
if(Rnode1 == Rnode2)
{
return Rnode2;
}
Rnode1 = Rnode1 -> next;
Rnode2 = Rnode2 -> next;
}
return nullptr;
}
};
5. 代码注释详解
- 注释1:先对头指针进行判空。以免造成空指针访问。
- 注释2:定义fast和slow快慢指针,并让他们在环中相遇。
- 注释3:如果point == nullptr则说明链表没环,返回nullptr。
- 注释4:让RmNode结点从point->next开始(快慢指针相遇点的下一个结点)往后走,再用count计数环中的节点数。
- 注释5:让Rnode1从头开始向后走count步。
- 注释6:让Rnode1 和 Rnode2 同时往后走,相遇点就是环的入口节点。
找入口结点的算法复杂度为:
- 时间复杂度:O(n)
- 空间复杂度:O(1)
1.如有错误或者没能理解的地方,请及时评论或者私信,及时修改更新
。
2.会持续更新相关链表高频题目,分类专栏—数据结构
。