【数据结构】有关环形链表题目的总结

文章目录

  • [引入 - 快慢指针](#引入 - 快慢指针)
  • [思考 - 快慢指针行走步数](#思考 - 快慢指针行走步数)
  • [进阶 - 寻找环形链表的头](#进阶 - 寻找环形链表的头)

引入 - 快慢指针

141-环形链表 - Leetcode

关于这道题,大家可以利用快慢指针,一个每次走两步,一个每次走一步,只要他们有一次相撞了就代表说这是一个链表

为了更好的理解我们可以代入下图

我们假设slow 进环的时侯,fast 已经走了C(环形区域的总长度)-N 步了,那么它就距离slow 刚刚好N 步于是乎没进行一次移动,即fast 往前走2步,slow 往前走一步,那么它们之间的距离就是N-1 步以此类推直到0

所以这一题的解答代码就是

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    if(head == NULL)
        return false;
    ListNode *fast = head, *slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
            return true;
    }
    return false;
}

思考 - 快慢指针行走步数

根据上面快指针一次走两步,慢指针一次走一步,我们可以得到结果并知晓原理

但如果快指针一次走的是三步呢,结果还会一样吗。

为此,我们不妨罗列一下三步的情况

假设一次走三步,我们在不分 C(环形区域的总长度) 的情况下,它们之间的距离就会是N -> N-2 -> N-4 -> ...

因为不分奇偶就无法得出最后结果,所以我们可以得到下面这个分类讨论

即:

我们发现一旦 C(环形区域的总长度) 为奇数的话,就会导致最后快指针比慢指针多走了一步,这就会导致,追不上吗,

但真的会这样吗

大家肯定会反应过来, C(环形区域的总长度) 的总长度是不会变的,变得只是快慢指针之间的距离,如果在进行一次循环我们可以将 N 的初始值看成 C-1 了,而N 每次移动都需要 -2 ,并且 C 为奇数,因此这一次,就可以看成偶数 的这种情况了,这样就能抓到了

同样的我们如果将这种情况以数学公式表示

这是快指针步数为3的情况,为4,为5的讨论情况也差不多这样,无非就是再讨论一下,这里就不赘述了


进阶 - 寻找环形链表的头

142 - 环形链表Ⅱ - Leetcode

乍一看,这道题与上面一道题基本一样,但是细看我们会发现这里返回开始入环的第一个节点,所以还是需要思考

如果有环的话,创建两个指针,一个指针从head节点开始,另一个指针从相遇点meet开始,两个指针每次都走一步,两个指针相遇的点就是链表入环的第一个节点。

因此在上面引入那道题的基础上我们需要增进一步


即为L距离就等于meet在环中转x-1圈,再走C-N,所以说meet和head的相遇点一定是链表入环的第一个节点。

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    
    if(head == NULL)
        return NULL;
    ListNode *fast = head, *slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
        {
            ListNode* phead = head;
            ListNode* meet = slow;
            while(phead != meet)
            {
                phead = phead->next;
                meet = meet->next;
            }
            return meet;
        }
    }
    return NULL;
}
相关推荐
打码农的篮球20 分钟前
STL——list
开发语言·c++·list
C++ 老炮儿的技术栈1 小时前
在 Scintilla 中为 Squirrel 语言设置语法解析器的方法
linux·运维·c++·git·ubuntu·github·visual studio
@蓝莓果粒茶2 小时前
LeetCode第350题_两个数组的交集II
c++·python·学习·算法·leetcode·职场和发展·c#
设计师小聂!2 小时前
力扣热题100----------53最大子数组和
java·数据结构·算法·leetcode
YouQian7722 小时前
问题 C: 字符串匹配
c语言·数据结构·算法
yanxing.D3 小时前
408——数据结构(第二章 线性表)
数据结构·算法
艾莉丝努力练剑3 小时前
【LeetCode&数据结构】二叉树的应用(二)——二叉树的前序遍历问题、二叉树的中序遍历问题、二叉树的后序遍历问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
Jackilina_Stone4 小时前
【faiss】用于高效相似性搜索和聚类的C++库 | 源码详解与编译安装
android·linux·c++·编译·faiss
喜欢吃燃面4 小时前
C++:list(1)list的使用
开发语言·c++·学习
waveee1234 小时前
学习嵌入式的第三十三天-数据结构-(2025.7.25)服务器/多客户端模型
服务器·数据结构·学习