数据结构 【带环链表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;
}
相关推荐
是糖不是唐14 分钟前
代码随想录算法训练营第五十三天|Day53 图论
c语言·数据结构·算法·图论
DC妙妙屋14 分钟前
11.19.2024刷华为OD
数据结构·链表·华为od
理论最高的吻4 小时前
98. 验证二叉搜索树【 力扣(LeetCode) 】
数据结构·c++·算法·leetcode·职场和发展·二叉树·c
木向5 小时前
leetcode:114. 二叉树展开为链表
算法·leetcode·链表
灼华十一6 小时前
算法编程题-排序
数据结构·算法·golang·排序算法
一子二木生三火6 小时前
IO流(C++)
c语言·开发语言·数据结构·c++·青少年编程
先鱼鲨生6 小时前
排序【数据结构】【算法】
数据结构·算法·排序算法
daily_23337 小时前
数据结构——小小二叉树第二幕(二叉树链式结构的实现以及二叉树的遍历)超详细!!!
数据结构·c++
小小白白蛆7 小时前
剑指offer JZ51 数组中的逆序对
数据结构·算法·排序算法