LeetCode热题100(二十六) —— 142.环形链表II

LeetCode热题100(二十六) ------ 142.环形链表II

题目描述

复制代码
给定一个链表的头节点head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 
为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
如果 pos 是 -1,则在该链表中没有环。
注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
     不允许修改 链表。
     
示例 1:
        输入:head = [3,2,0,-4], pos = 1
        输出:返回索引为 1 的链表节点
        解释:链表中有一个环,其尾部连接到第二个节点。
复制代码
示例 2:
        输入:head = [1,2], pos = 0
        输出:返回索引为 0 的链表节点
        解释:链表中有一个环,其尾部连接到第一个节点。
复制代码
示例 3:
        输入:head = [1], pos = -1
        输出:返回 null
        解释:链表中没有环。
复制代码
提示:
        链表中节点的数目范围在范围 [0, 104] 内
        -105 <= Node.val <= 105
        pos 的值为 -1 或者链表中的一个有效索引
        
进阶:你是否可以使用 O(1) 空间解决此题?

代码实现

  • 思路一:哈希表
java 复制代码
public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        ListNode node = head;
        while (node != null) {
            if (set.contains(node)) {
                return node;
            } else {
                set.add(node);
            }
            node = node.next;
        }
        return null;
    }
}
  • 思路二:快慢指针
java 复制代码
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                ListNode node = head;
                while (node != slow) {
                    node = node.next;
                    slow = slow.next;
                }
                return node;
            }
        }
        return null;
    }
}
  • 数据结构
java 复制代码
class ListNode {
	int val;
	ListNode next;
	ListNode(int x) {
		val = x;
		next = null;
	}
}

思路解析

  1. 输入:链表头节点 ListNode head
  2. 输出:链表成环节点 ListNode cycleNode 无环则返回 null
  3. 思路一:哈希表 HashSet
    • 关键:尾节点的 next 指向
      • 无环,next == null
      • 有环,next -> node 链表中某个节点
      • 有环,遍历链表,当某个节点被第二次访问到时,它就是尾节点的next
    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)
  4. 思路二:快慢指针
    • 慢指针slow一次移动1个位置,快指针fast一次移动2个位置
      • 无环,fast 指针将先走到尾节点或尾节点的前一个节点,其后 next == null
      • 有环,快指针将追上慢指针,二者相遇
    • 关键节点:入环节点 C & 相遇节点 M
    • 关键思路:快慢指针相遇后到入环节点的距离等于头节点到入环节点的距离
  • 推理逻辑:
    • 设定参数
      • L :头节点到入环节点的距离
      • T :入环节点到相遇节点的距离
      • R :相遇节点到入环节点的距离
    • 当快慢指针相遇时
      • 慢指针移动距离:L + T
      • 快指针移动距离:L + q * (T + R) + T
        • 其中 q*(T+R)代表快指针先经过入环节点并已走完 q(q = 1,2,3,...)
      • 同时,快指针移动距离 = 慢指针的两倍,即 L + q * (T + R) + T = 2 * (L + T)
      • 化简公式:(q - 1) * (T + R) + R = L 可推理出 R = L
      • 等式左侧:从相遇节点 M 起走到入环节点 C (经过 q-1圈)
      • 等式右侧:从头节点 head 起走到入环节点 C
  • 时间复杂度: O ( n ) O(n) O(n) = O ( n ) + O ( n ) O(n)+O(n) O(n)+O(n)
    • 虽然是双循环嵌套,但满足条件的内层循环只执行1次
    • 外层循环寻找相遇节点,慢指针移动不超过 n 次,寻找过程不触发内层循环执行
    • 内层循环寻找入环节点,指针移动不超过 n 次,相遇后内层循环执行完直接return
  • 空间复杂度: O ( 1 ) O(1) O(1) 只用了3个指针
  1. 相关知识点

相关推荐
sheeta199815 小时前
LeetCode 每日一题笔记 日期:2026.05.07 题目:3660. 找到所有可以到达的最大值
笔记·算法·leetcode
经济元宇宙15 小时前
哪款工业仿真软件上手简单?企业常用款推荐
人工智能·算法
Hesionberger15 小时前
LeetCode79:单词搜索DFS回溯详解
java·开发语言·c++·python·算法·leetcode·c#
纪伊路上盛名在15 小时前
聊一聊关于gene的富集分析
算法·数据分析·统计分析·计算生物·gene
米粒116 小时前
力扣算法刷题 Day 62 最短路算法
算法·leetcode·职场和发展
时空自由民.16 小时前
三个按键的,短按1S,长按3S,单击,双击,三击的检测程序
大数据·数据库·计算机网络·算法
dog25016 小时前
圆锥曲线命题的定义和证明
网络·算法·php
IT猿手16 小时前
光伏模型参数估计:山羊优化算法(Goat Optimization Algorithm, GOA)求解光伏模型参数辨识问题,免费提供完整MATLAB代码链接
开发语言·算法·matlab·智能优化算法·光伏模型参数估计·光伏模型参数辨识·最新群智能算法
嵌入式小企鹅17 小时前
大模型算法工程师面试宝典
人工智能·学习·算法·面试·职场和发展·大模型·面经
我不是懒洋洋17 小时前
手写一个并查集:从原理到最小生成树实战
c语言·c++·经验分享·算法