牛客经典链表题—(NC3)链表中环的入口结点

满难度系数 * * * * *,此题难度系数 * * *
满考频热度 * * * * *,此题热度 * * * * *

1. 题目描述

在这里插入图片描述

2. 题目链接

  1. 牛客题目链接链表中环的入口结点

3. 题目剖析

  1. 先判断链表中是否有环,没有则就没有入口结点,直接返回null。是否有环link
  2. 如果链表中有环,遍历时不会走到nullptr,定义一个fast指针和slow指针。当fast和slow进环以就会围着环同时运动,且fast比slow每次多走一步。直到fast和slow相遇
  3. 相遇的点肯定是环里面,然后定义一个count,在定义一个结点RmNode从相遇结点的下一个结点开始,每走一步count++,再走到这个结点时,count就是这个环里面有多少个结点
  4. 再定义两个结点Rnode1,Rnode2都从头开始,让Rnode1先走count步
  5. 再让Rnode1,Rnode2同时走,相遇点就是环的入口结点。

3.1剖析图示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 图示详解

  1. 先让快慢指针在环中相遇。图一
  2. 从相遇点的下一个开始,计算环里面有几个结点。图二
  3. 定义两个结点都从头开始,让一个结点先走环里面的节点数,然后两个环在同时走。图三

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. 注释1:先对头指针进行判空。以免造成空指针访问。
  2. 注释2:定义fast和slow快慢指针,并让他们在环中相遇。
  3. 注释3:如果point == nullptr则说明链表没环,返回nullptr。
  4. 注释4:让RmNode结点从point->next开始(快慢指针相遇点的下一个结点)往后走,再用count计数环中的节点数。
  5. 注释5:让Rnode1从头开始向后走count步。
  6. 注释6:让Rnode1 和 Rnode2 同时往后走,相遇点就是环的入口节点。

找入口结点的算法复杂度为:

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

1.如有错误或者没能理解的地方,请及时评论或者私信,及时修改更新
2.会持续更新相关链表高频题目,分类专栏—数据结构

猜你喜欢

转载自blog.csdn.net/weixin_45313447/article/details/115324679