力扣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;
    }
};
相关推荐
Zachery Pole4 小时前
CCF-CSP备战NO.5链表(1)
数据结构·链表
圣光SG7 小时前
Java操作题练习(七)
java·开发语言·算法
Cx330_FCQ8 小时前
Tmux使用
服务器·git·算法
拳里剑气9 小时前
C++算法:多源BFS
c++·算法·宽度优先·多源bfs
ysa05103010 小时前
【板子】短序列dp(换成维护更小常数维度的dp)
c++·笔记·算法·板子
shwill12310 小时前
PID 算法(三)--- 增量 PID ↔ 单神经元 PID 等价映射
linux·算法
wabs66611 小时前
关于图论【卡码网110.字符串迁移的思考】
数据结构·算法·图论
hanlin0311 小时前
刷题笔记:力扣第242、349题(哈希表)
笔记·算法·leetcode
浮沉98712 小时前
二分查找算法例题(二)
算法
only-qi13 小时前
大模型Agent面试攻略:落地工程痛点、评估体系与Agentic RAG核心精讲
人工智能·算法·面试·职场和发展·langchain·rag