数据结构 【带环链表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;
}
相关推荐
好易学·数据结构27 分钟前
可视化图解算法72:斐波那契数列
数据结构·算法·leetcode·动态规划·力扣·牛客网
CoderYanger2 小时前
A.每日一题——3432. 统计元素和差值为偶数的分区方案
java·数据结构·算法·leetcode·1024程序员节
博语小屋2 小时前
线程同步与条件变量
linux·jvm·数据结构·c++
Ayanami_Reii2 小时前
进阶数据结构-AC自动机
数据结构·算法·动态规划·字符串·ac自动机
带鱼吃猫2 小时前
数据结构:顺序表与基于动态顺序表的通讯录项目
数据结构·链表
报错小能手2 小时前
数据结构 AVL二叉平衡树
数据结构·算法
liu****3 小时前
20.预处理详解
c语言·开发语言·数据结构·c++·算法
代码游侠3 小时前
数据结构——哈希表
数据结构·笔记·学习·算法·哈希算法·散列表
小龙报4 小时前
【算法通关指南:数据结构与算法篇】树形结构遍历指南:DFS 递归深搜与 BFS 队列广搜实战解析
c语言·数据结构·c++·算法·链表·深度优先·visual studio
Aurorar0rua4 小时前
C Primer Plus 14.17 复习题
c语言·开发语言·数据结构