【力扣】203、环形链表 II

142. 环形链表 II

要解决这道题,首先需要对问题进行拆解:

  1. 确定链表是否存在环
  2. 确定环的入口点

如何判断是否存在环呢?这个比较容易想到,使用快慢指针即可判断链表是否存在环。我们定义两个指针:

复制代码
ListNode slow = head;
ListNode fast = head;

让 fast 指针的移动速度是 slow 指针的两倍即可,当它们再次相遇时,说明 fast 指针比 slow 指针多走了一圈,并重新追上 slow 指针了,此时可以说明链表存在环。

复制代码
while(fast != null && fast.next != null) {
    slow = slow.next;
    fast = fast.next.next;
    // 如果慢指针追上快指针,说明存在环
    if(slow == fast) {
        ...
    }
}
return null;

如何确定环的入口点呢?这涉及到数学推导,这一步不太容易想到:

让我们假设三个变量 x,y,z

可以得到公式如下:

复制代码
slow指针走过的距离 * 2 = fast指针走过的距离
于是得到等式如下:
2(x + y) = (x + y) + n(y + z)		// n(y+z)表示fast指针绕环的长度
x + y = n(y + z)
x = nz + (n - 1)y
x = (n - 1)(z + y) + z

因此我们可以知道,在 slow 指针和 fast 指针相遇的节点处,满足该等式:x = (n - 1)(z + y) + z

这个式子表示什么呢?表示一个指针从头节点处出发,到环型入口处经过的距离 x 等于另一个指针从 slow 和 fast 相交的节点处出发,经过 z + (n - 1)(z + y),即走过 z 距离并绕环 n-1 圈,至于这个 n 是多少我们不必知道,于是可以得到以下代码:

复制代码
// 通过数学规律发现,相交的节点到环的入口处的节点数等于头节点到环入口处的节点数
ListNode temp = head;
// 如果存在环,必定不会死循环
while(temp != slow) {
    temp = temp.next;
    slow = slow.next;
}
return slow;

至此,题解,完整 Java 代码如下:

复制代码
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            // 如果慢指针追上快指针,说明存在环
            if(slow == fast) {
                // 通过数学规律发现,相交的节点到环的入口处的节点数等于头节点到环入口处的节点数
                ListNode temp = head;
                // 如果存在环,必定不会死循环
                while(temp != slow) {
                    temp = temp.next;
                    slow = slow.next;
                }
                return slow;
            }
        }
        return null;
    }
}
相关推荐
小猫咪怎么会有坏心思呢33 分钟前
华为OD机考 - 水仙花数 Ⅰ(2025B卷 100分)
数据结构·链表·华为od
hn小菜鸡1 小时前
LeetCode 1356.根据数字二进制下1的数目排序
数据结构·算法·leetcode
全栈凯哥4 小时前
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
java·算法·leetcode·链表
全栈凯哥4 小时前
Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解
java·算法·leetcode·链表
SuperCandyXu4 小时前
leetcode2368. 受限条件下可到达节点的数目-medium
数据结构·c++·算法·leetcode
lyh13445 小时前
【SpringBoot自动化部署方法】
数据结构
MSTcheng.5 小时前
【数据结构】顺序表和链表详解(下)
数据结构·链表
慢半拍iii6 小时前
数据结构——F/图
c语言·开发语言·数据结构·c++
m0_637146936 小时前
零基础入门 C 语言基础知识(含面试题):结构体、联合体、枚举、链表、环形队列、指针全解析!
c语言·开发语言·链表
iceslime7 小时前
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
数据结构·c++·算法·算法设计与分析