当前位置: 首页 > article >正文

环形链表问题的探究与代码实现

在数据结构与算法的学习中,环形链表是一个经典的问题。它不仅考察对链表这种数据结构的理解,还涉及到指针操作和逻辑推理。本文将结合代码和图文,深入分析如何判断链表中是否有环以及如何找到环的入口点。
 

目录

一、判断链表中是否有环 

​编辑代码实现(C语言)

 

二、找到环形链表的入口点 ​编辑

思路一 

代码实现(C语言) 

思路二:转换为找链表交点 

代码实现(C语言) 

三、总结 


仓库 https://blog.csdn.net/nplplus/category_12904039.html

作者主页  共享家9527-CSDN博客

一、判断链表中是否有环
 


判断链表中是否存在环,常用的方法是快慢指针法。
 
思路
 
定义两个指针,慢指针(slow)每次移动一个节点,快指针(fast)每次移动两个节点。如果链表中存在环,那么快指针最终一定会追上慢指针;如果不存在环,快指针会先到达链表末尾。
 

错误思想


代码实现(C语言)

 


c
  
bool hasCycle(struct ListNode *head) {
    struct ListNode* slow, *fast;
    slow = fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
            return true;
    }
    return false;
}
 


分析
 


在上述代码中,初始化快慢指针都指向链表头节点。在循环中,不断移动快慢指针。当快慢指针相遇时,说明链表存在环,返回 true ;如果循环结束,快指针到达链表末尾,说明链表无环,返回 false 。
 


二、找到环形链表的入口点
 


找到环形链表的入口点同样可以使用快慢指针法,并且在找到相遇点后,通过数学推导得出结论来找到入口点。同时,还可以将找入口点的问题巧妙地转换成找链表交点的问题,以下为您详细介绍两种思路。
 


思路一
 


首先使用快慢指针找到相遇点。
 
假设起始点到入口点距离为 L ,入口点到相遇点距离为 X ,环的长度为 C 。当快慢指针相遇时,慢指针走过的距离为 L + X ,快指针走过的距离为 L + n*C + X ( n 为快指针在环中绕的圈数),且快指针走过的距离是慢指针的2倍,即 2*(L + X) = L + n*C + X ,化简可得 L = n*C - X 。
 
从结论可以看出,一个指针从相遇点走,一个指针从起始点走,它们会在入口点相遇。
 


代码实现(C语言)
 


c
  
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast, *slow;
    fast = slow = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) {
            struct ListNode* meet = slow;
            struct ListNode* start = head;
            while (meet != start) {
                meet = meet->next;
                start = start->next;
            }
            return meet;
        }
    }
    return NULL;
}


 
 



思路二:转换为找链表交点
 


图片中的代码展示了将找环形链表入口点转换为找链表交点的方法。当快慢指针相遇后:
 
定义 meet 指针指向相遇点,此时 struct ListNode* meet = slow;  。
 
定义 lt1 指针从相遇点的下一个节点开始,即 struct ListNode* lt1 = meet->next;  。
 
定义 lt2 指针指向链表头节点,即 struct ListNode* lt2 = head;  。
 
将相遇点的next指针置为 NULL ,即 meet->next = NULL;  ,这样就把原环形链表处理成了两个普通链表。
 
最后通过调用 getIntersectionNode(lt1, lt2) 函数来获取这两个链表的交点,该交点就是原环形链表的入口点。
 


代码实现(C语言)
 


c
  
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast, *slow;
    fast = slow = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) {
            // 转换成lt1和lt2求交点
            struct ListNode* meet = slow;
            struct ListNode* lt1 = meet->next;
            struct ListNode* lt2 = head;
            meet->next = NULL;
            return getIntersectionNode(lt1, lt2);
        }
    }
    return NULL;
}


 
 
分析
 
通过这两种方法,都能有效地找到环形链表的入口点。第一种方法基于数学推导,利用相遇点和起始点到入口点的关系;第二种方法则通过巧妙地转换问题,将找环形链表入口点变为找两个普通链表的交点。无论哪种方法,都体现了算法设计中利用已有结论和转换思路来解决问题的技巧。在实际应用中,类似的思路也可以用于解决一些与循环、追踪路径相关的问题。
 


三、总结
 


环形链表问题是算法学习中的一个重要知识点。通过快慢指针法,我们可以高效地判断链表是否有环以及找到环的入口点。理解这个问题不仅有助于加深对链表数据结构的认识,还能提升逻辑思维和算法设计能力。在实际应用中,类似的思路也可以用于解决一些与循环、追踪路径相关的问题。


http://www.kler.cn/a/578606.html

相关文章:

  • 【论文精读】GaussReg: Fast 3D Registration with Gaussian Splatting
  • MyBatis SQL 映射文件的作用和结构
  • Java 大视界 -- Java 大数据在智能体育赛事运动员表现分析与训练优化中的应用(122)
  • 忘记dedecms后台超级管理员账号和密码的解决方案
  • crewai框架出现SSLError
  • 请谈谈 HTTP 中的安全策略,如何防范常见的Web攻击(如XSS、CSRF)?
  • 2025-03-09 学习记录--C/C++-PTA 练习11-4 字符定位(最后一次找到的字符)
  • 音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构
  • 同为科技智能PDU在数据中心场景的应用与解决方案
  • 垂直领域大模型优化:从“通用”到“专精”——打造医疗、金融、法律领域的AI专家
  • 【RAG】文本分割的粒度
  • es-使用easy-es时如何指定索引库
  • 【Java篇】数据类型与变量:窥见程序的天地万象
  • 设计模式 一、软件设计原则
  • VSCode输入npm xxx,跳转到选择应用
  • 云原生时代的架构革新,Apache Doris 存算分离如何实现弹性与性能双重提升
  • 计算机视觉图像点运算【灰度直方图均衡化图形界面实操理解 +开源代码】
  • 如何关闭 MySQL 的 binlog(Binary Log)日志
  • MMFewShot
  • 【Python】为什么要写__init__.py