力扣hot100-141.环形链表

这是一个经典的链表问题,通常被称为"判断链表是否有环"。

解决这个问题的标准且最高效的解法是 快慢指针算法(也称为 Floyd 判圈算法或龟兔赛跑算法)。

解题思路

  1. 定义两个指针

    • 慢指针 (slow):一次走一步。

    • 快指针 (fast):一次走两步。

  2. 逻辑分析

    • 如果没有环fast 指针走得快,最终会遇到 NULL(即到达链表末尾),此时可以直接返回 false

    • 如果有环fast 指针会率先进入环,并在环内循环。当 slow 指针也进入环后,这就变成了一个"追及问题"。因为 fastslow 每次多走一步,所以在有限的步数内,fast 一定会追上 slow(即 fast == slow)。

  3. 复杂度

    • 时间复杂度O(n)。如果无环,遍历一次;如果有环,快指针在环内绕圈追上慢指针的时间也是线性的。

    • 空间复杂度O(1)。只使用了两个指针,不需要额外的哈希表来存储已访问的节点。

下面是完整的代码实现,包含了解题类和用于构建带环链表进行测试的 main 函数。

代码要点

  1. 初始化slowfast 都指向 head。有些写法会让 fast 初始指向 head->next,这也是可以的,但循环条件和判断逻辑稍微不同。让它们都从 head 开始是最直观的。

  2. 循环条件while (fast != NULL && fast->next != NULL)。这个条件非常关键,它保证了 fast->next->next 不会出现空指针异常。

  3. 相遇判断 :在移动指针之后立即检查 if (slow == fast)。如果相等,说明快指针追上了慢指针,链表有环。

  4. 返回结果:如果循环正常退出,说明快指针遇到了空指针,链表没有环。

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL ||  head->next == NULL)
            return false;
        
        ListNode* fast = head;
        ListNode* slow = head;
        
        while(fast != nullptr && fast->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
                return true;
        }

        return false;
    }
};
相关推荐
艾莉丝努力练剑9 分钟前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
偷吃的耗子40 分钟前
【CNN算法理解】:CNN平移不变性详解:数学原理与实例
人工智能·算法·cnn
dazzle2 小时前
机器学习算法原理与实践-入门(三):使用数学方法实现KNN
人工智能·算法·机器学习
那个村的李富贵2 小时前
智能炼金术:CANN加速的新材料AI设计系统
人工智能·算法·aigc·cann
张张努力变强2 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
万岳科技系统开发2 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
wWYy.2 小时前
数组快排 链表归并
数据结构·链表
张登杰踩2 小时前
MCR ALS 多元曲线分辨算法详解
算法
YuTaoShao2 小时前
【LeetCode 每日一题】3634. 使数组平衡的最少移除数目——(解法一)排序+滑动窗口
算法·leetcode·排序算法
波波0072 小时前
每日一题:.NET 的 GC是如何分代工作的?
算法·.net·gc