【Hot 100 刷题计划】 LeetCode 141. 环形链表 | C++ 哈希表直觉解法

LeetCode 141. 环形链表

📌 题目描述

题目级别:简单

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。

如果链表中存在环 ,则返回 true 。 否则,返回 false


💡 解法一:哈希表备忘录

判断是否"绕圈子",最符合人类直觉的思维方式就是"记事本法"。

我们在遍历链表的过程中,把路过的每一个节点的内存地址都记在小本本(哈希表)上。

每次往前走一步,都先查一下本子:

  1. 如果这个地址本子上没有,就把它记下来,继续往下走。
  2. 如果走到某个节点,发现它的地址竟然已经在本子上了!这说明我们回到了曾经来过的地方,必定有环
  3. 如果一路走到 nullptr 都没有重复,说明链表是一条直到尽头的直线,没有环。

💻 C++ 代码实现 (哈希表法)

cpp 复制代码
class Solution {
public:
    bool hasCycle(ListNode *head) {
        // 使用 unordered_set 记录访问过的节点指针
        unordered_set<ListNode*> seen;
        
        while (head != nullptr)
        {
            // 如果在集合中找到了当前节点,说明绕回来了
            if (seen.count(head)) return true;
            
            // 没找到,就把它加入集合,留下访问记录
            seen.insert(head);
            
            // 继续往下走
            head = head->next;
        }

        // 走到尽头了,说明没环
        return false;
    }
};

💡 解法二:Floyd 快慢指针 (龟兔赛跑)

为了彻底消灭哈希表带来的空间消耗,我们可以引入两个不同速度的指针:

  • 慢指针 (slow):每次只走 1 步。
  • 快指针 (fast):每次走 2 步。

这就是著名的"龟兔赛跑"算法。

  • 情况 1:没有环 。快指针跑得快,它(或者它的下一步)会率先到达跑道的尽头 nullptr。比赛直接结束,判定无环。
  • 情况 2:有环 。这就非常有意思了。快指针会率先进入环内,并在环里无休止地打转。当慢指针也进入环内时,这场赛跑就变成了操场上的追击战。因为快指针每次比慢指针多走一步,所以无论两人的初始距离多远,快指针最终一定会以每次缩短 1 步的进度,从后面稳稳地"追上"(重合)慢指针!

只要两个指针重合了,就说明一定存在环!


💻 C++ 代码实现 (快慢指针法)

cpp 复制代码
class Solution {
public:
    bool hasCycle(ListNode *head) {
        // 空链表或只有一个节点的链表肯定无环
        if (head == nullptr || head->next == nullptr) return false;

        ListNode* slow = head;
        ListNode* fast = head->next;

        // 只要没相遇,比赛就继续
        while (slow != fast) {
            // 如果快指针走到尽头,说明跑道是直的,无环
            if (fast == nullptr || fast->next == nullptr) {
                return false;
            }
            // 慢指针走一步
            slow = slow->next;
            // 快指针走两步
            fast = fast->next->next;
        }

        // 循环被打破,说明 slow == fast,套圈相遇了!有环!
        return true;
    }
};
相关推荐
如竟没有火炬8 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi88 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
Qt程序员9 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
想吃火锅100510 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
qeen8710 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习
王老师青少年编程10 小时前
信奥赛C++提高组csp-s之搜索进阶(记忆化搜索案例实践3)
c++·记忆化搜索·方格取数·csp·信奥赛·csp-s·提高组
Titan202411 小时前
Linux动静态库
linux·服务器·c++
j_xxx404_12 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
wuminyu12 小时前
Java锁机制之park和unpark源码剖析
java·linux·c语言·jvm·c++
玖玥拾13 小时前
C/C++ 基础笔记(十一)类的进阶
c语言·c++·设计模式·