数据结构 【带环链表2】

说到带环链表,有一道题目是这样说的,如果一个链表存在环,那么就返回进入环的第一个节点,如果链表没有环,那么就返回空。这里给出两种解题思路:

第一种解法:小结论解法

分析:这道题目可以拆分成两个部分,第一:检查链表是否带环。第二:返回带环链表的第一个进环节点。对于第一个部分,可以使用快慢指针的方式进行检测,这里再理一下思路:

· 关于第二点,这里先给出一个结论:假设存在两个指针meet和start,meet从fast和slow相遇的位置出发,start从链表的起点出发,那么meet和start一定会在链表刚进环的节点相遇。

这里给出证明过程:假设有一个带环链表如下图所示:

证明结果续:

所以算法的设计思路为:当meet和start从相应的条件开始移动时,它们相遇的节点就是链表环的入口节点。代码实现如下:

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast,*slow;
    fast = slow = head;
    while(fast && fast->next)//检测是否带环
    {
        fast = fast->next->next;
        slow = slow->next;

        if(fast == slow)//相遇说明有环
        {
            struct ListNode* meet = fast;
            struct ListNode* start = head;

            while(meet != start)//循环停止即为入口节点
            {
                meet = meet->next;
                start =start->next;
            }
            return meet;
        }
    }
    return NULL;
}

第二种解法:转换法(将环断开,转换成求链表的第一个交点问题)

随即问题得到转化,可以先计算headA和headB的长度,计算出长度之前的差值,让长的链表先走差值步,然后两个链表同时往后走,在第一次节点地址相同的位置时,就是两个链表的第一个交点。代码实现如下:

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast,*slow;
    fast = slow = head;

    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;

        if(slow == fast)
        {
            struct ListNode* headB = fast->next;
            fast->next = NULL;

            struct ListNode* tailA = head,*tailB = headB;
            int lenA = 1,lenB = 1;

            while(tailA->next)
            {
                tailA = tailA->next;
                lenA++;
            }

            while(tailB->next)
            {
                tailB = tailB->next;
                lenB++;
            }
            int gap = abs(lenA-lenB);
            struct ListNode* longNode = head,*shortNode = headB;
            if(lenA < lenB)
            {
                longNode = headB;
                shortNode = head;
            }

            while(gap--)
            {
                longNode = longNode->next;
            }

            while(longNode != shortNode)
            {
                longNode = longNode->next;
                shortNode = shortNode->next;
            }

            return longNode;

        }
    }
    return NULL;
}
相关推荐
xiangyun619 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun619 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法
OKkankan11 小时前
LangChain 能力详解!:输出解析、RAG、向量数据库与 Retriever 检索器
数据结构·python·langchain·ai应用
蓝速科技11 小时前
便民服务大厅 AI 数字人一体机场景适配与落地指南丨蓝速科技
大数据·网络·数据结构·人工智能·自然语言处理·数据分析·运维开发
xxwxx__11 小时前
C++ AVL 树深度剖析:平衡二叉搜索树原理、源码与面试考点
数据结构·c++
Logic10111 小时前
C语言/数据结构数组题解:数字列表加一(Plus One)——进位处理与数组扩展
c语言·数据结构·模拟·数组·时间复杂度·算法题·进位
xxwxx__15 小时前
C++ STL set 与 map 全套详解:关联式容器、红黑树底层、代码坑点、刷题实战
数据结构·c++
程曦曦15 小时前
MySQL 生产库误删 98 张表后的时间点恢复实战:从 binlog 解析到资金对账
linux·数据结构·其他·算法·ubuntu·运维开发
郝学胜-神的一滴16 小时前
Effective Python 条款 13:善用星号解包,告别下标切片拆分的坑
服务器·开发语言·数据结构·python·程序人生·pycharm
Logic10116 小时前
C语言/数据结构位运算题解:异或XOR找出流水线上的“独特零件编号“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质