数据结构 【带环链表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;
}
相关推荐
ysa0510301 小时前
虚拟位置映射(标签鸽
数据结构·c++·笔记·算法
Yue丶越1 小时前
【C语言】深入理解指针(二)
c语言·开发语言·数据结构·算法·排序算法
程序员东岸2 小时前
数据结构杂谈:双向链表避坑指南
数据结构·链表
Shinom1ya_2 小时前
算法 day 46
数据结构·算法
952362 小时前
数据结构-链表
java·数据结构·学习
小龙报4 小时前
算法通关指南:数据结构和算法篇 --- 队列相关算法题》--- 1. 【模板】队列,2. 机器翻译
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
晨非辰4 小时前
【数据结构初阶】--从排序算法原理分析到代码实现操作,参透插入排序的奥秘!
c语言·开发语言·数据结构·c++·算法·面试·排序算法
三川6985 小时前
排序算法介绍
数据结构·算法·排序算法
学编程就要猛14 小时前
数据结构初阶:Java中的Stack和Queue
数据结构
是苏浙14 小时前
零基础入门C语言之C语言实现数据结构之顺序表
c语言·开发语言·数据结构