力扣hot100:环形链表II(哈希算法与快慢指针法思路讲解)

题目概述

方法一:哈希表法 - 直观空间换时间

思路分析

使用哈希表存储遍历过的节点,当遇到重复节点时,该节点即为环的入口。这种方法思路简单直接,利用了哈希表的快速查找特性。

代码实现

java 复制代码
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode pos = head;
        Set<ListNode> visited = new HashSet<>(); // 存储已访问节点
        while (pos != null) {
            if (visited.contains(pos)) { // 发现重复节点
                return pos; // 返回环的入口
            } else {
                visited.add(pos); // 记录访问过的节点
            }
            pos = pos.next; // 移动到下一个节点
        }
        return null; // 遍历结束无环
    }
}

复杂度分析

  • 时间复杂度:O(n)。每个节点只需访问一次。
  • 空间复杂度:O(n)。最坏情况下需要存储所有节点。

方法二:快慢指针法(Floyd 算法)- 空间高效的数学解法

思路分析

  1. 判断是否有环:使用快指针(每次两步)和慢指针(每次一步),若两指针相遇则有环
  2. 寻找环入口:相遇后将一个指针移回头部,两指针每次一步移动,再次相遇点即为环入口

数学证明

设:

  • 头节点到环入口距离为 a
  • 环入口到相遇点距离为 b
  • 相遇点到环入口距离为 c
  • 环长度:L = b + c

当快慢指针相遇时:

  • 慢指针路程:a + b
  • 快指针路程:a + b + kL(绕环 k 圈)
  • 快指针路程 = 2 × 慢指针路程
  • 2(a + b) = a + b + k(b + c)
  • 化简得:a = (k-1)L + c

这表明:头节点到环入口距离 = 相遇点到环入口距离 + (k-1)圈环长,因此两指针将在环入口相遇。

代码实现

java 复制代码
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        
        while (fast != null) {
            // 快指针移动前的边界检查
            if (fast.next == null) {
                return null; // 无环
            }
            fast = fast.next.next; // 快指针移动两步
            slow = slow.next;      // 慢指针移动一步
            
            // 发现环时
            if (slow == fast) {
                ListNode temp = head; // 新指针从头出发
                // 两指针同步移动直到相遇
                while (temp != slow) {
                    temp = temp.next;
                    slow = slow.next;
                }
                return slow; // 返回环入口
            }
        }
        return null; // 遍历结束无环
    }
}

复杂度分析

  • 时间复杂度:O(n)。线性遍历链表。
  • 空间复杂度:O(1)。仅使用固定指针。

两种方法对比

方法 时间复杂度 空间复杂度 优势
哈希表法 O(n) O(n) 实现简单,逻辑直观
快慢指针法 O(n) O(1) 空间高效,数学原理精妙

总结

  1. 面试推荐:优先使用快慢指针法,尤其面试官关注空间复杂度时
  2. 实用场景:哈希表法在小规模数据或非性能关键场景更易实现
  3. 关键技巧:Floyd 算法的第二阶段(移动头指针与相遇点指针)是找到环入口的精髓

理解这两种解法不仅能解决本题,还能为解决其他链表环问题打下坚实基础。快慢指针法中蕴含的数学原理尤其值得深入体会!

掌握环形链表检测的核心思想,你就能轻松应对链表相关的各类环检测问题!

相关推荐
云泽808几秒前
C/C++内存管理详解:从基础原理到自定义内存池原理
java·c语言·c++
cyclel6 分钟前
散列表的小想法
算法
Code小翊9 分钟前
堆的基础操作,C语言示例
java·数据结构·算法
余俊晖9 分钟前
如何让多模态大模型学会“自动思考”-R-4B训练框架核心设计与训练方法
人工智能·算法·机器学习
Emilia486.16 分钟前
【Leetcode&nowcode&数据结构】顺序表的应用
数据结构·算法·leetcode
一水鉴天22 分钟前
整体设计 逻辑系统程序 之27 拼语言整体设计 9 套程序架构优化与核心组件(CNN 改造框架 / Slave/Supervisor/ 数学工具)协同设计
人工智能·算法
高山上有一只小老虎27 分钟前
idea中设置快捷键风格
java·ide·intellij-idea
JH307328 分钟前
IDEA自带的Maven安装位置
java·maven·intellij-idea
小年糕是糕手31 分钟前
【数据结构】双向链表“0”基础知识讲解 + 实战演练
c语言·开发语言·数据结构·c++·学习·算法·链表
将车24437 分钟前
C++实现二叉树搜索树
开发语言·数据结构·c++·笔记·学习