力扣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;
    }
};
相关推荐
workflower13 分钟前
基于机器学习的设备故障预测分析方法
人工智能·算法·机器学习·设计模式·语言模型·自然语言处理·重构
格发许可优化管理系统18 分钟前
Mentor许可证与其他软件许可证的深度比较
java·大数据·运维·c语言·c++·算法
wjcroom25 分钟前
时空和电子7-泡力模型含罗量
人工智能·算法·机器学习
KaMeidebaby29 分钟前
卡梅德生物技术快报 | Fab 合成文库构建与抗体筛选实验流程及数据解析
人工智能·python·tcp/ip·算法·机器学习
金融小师妹32 分钟前
基于AI事件驱动模型与验证溢价框架的市场分析:从预期交易到事实验证,原油与黄金面临关键定价重构
大数据·人工智能·算法·均值算法·线性回归
xxwl58538 分钟前
工作室小测的部分记录
c++·学习·算法
智者知已应修善业42 分钟前
【51单片机串口通信甲机四个按键模拟四位二进制值发送乙机以十进制显示2位数码管】2024-6-14
c++·经验分享·笔记·算法·51单片机
KobeSacre42 分钟前
划分为k个相等的子集
算法·leetcode·深度优先
不会就选b44 分钟前
算法日常・每日刷题--<二分查找>2
算法
郝学胜_神的一滴1 小时前
完全二叉树与堆底层原理深度剖析 | 手写C++大顶堆实现
数据结构·算法