LeetCode hot 100 — 141. 环形链表2

题目信息

给定一个链表的头节点 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) 空间解决此题?

思路 / 启发过程

感想是看了答案我基本上不可能会做的....

我的理解上来说,答案的核心,首先要理解快慢指针的做法,然后就是用数学来解答。数学解答的核心偏向于距离表达和速度表达吧,去建立等量关系(相遇本质上就是一种路程相等的等量关系)。从表达式揭露的关系下手,然后去看怎么建立算法和解答方法

参考答案思维过程

关键是:相遇点到环入口的距离,和头节点到环入口的距离存在数学关系。

设:

复制代码
a:头节点到环入口的距离
b:环入口到相遇点的距离
c:环的长度

相遇时:

复制代码
slow 走了:a + b
fast 走了:a + b + k*c

这里注意一个细节,slow一定是在进入的第一圈就被fast追上了。原因:slow进入环后,和fast的距离肯定是 <= m的,而fast每次都会缩小和slow之间的,一个单位的距离,所以必定在slow走完第一个完整的环前,二者就相遇了。

因为 fast 速度是 slow 的两倍:

复制代码
2(a + b) = a + b + k*c

整理得到:

复制代码
a + b = k*c

所以:

复制代码
a = k*c - b

也即:

复制代码
a = (k - 1)c + (c - b)

这意味着:

复制代码
从相遇点继续走 c - b 步,会到达环入口
从头节点走 a 步,也会到达环入口

而多走完整的 (k - 1)c 圈不会改变环上的位置。

因此相遇后:

  1. 保留一个指针在相遇点。
  2. 把另一个指针重新放回头节点。
  3. 两个指针都每次走一步。
  4. 它们下一次相遇的位置就是环入口。

通过示例代码

python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 承接环形链表1的部分,先找到相遇点
        fast = head
        slow = head
        while fast is not None and fast.next is not None:
            slow = slow.next
            fast = fast.next.next
            if slow is fast:    # has circle
                # 开始找相遇节点
                fast = head # 一个节点回到头部位置
                while slow != fast:
                    fast = fast.next
                    slow = slow.next
                return fast
        return None

知道逻辑了以后写代码还是很好写的...主要是逻辑和思维过程

相关推荐
玖玥拾29 分钟前
LeetCode 202 快乐数
算法·leetcode
LuminousCPP32 分钟前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先
ZhouDevin2 小时前
算法论文/数据集3——CLD(TMLR2025)压缩训练集,仅保留对验证集有益的样本
人工智能·深度学习·算法·计算机视觉
Tim_102 小时前
【LeetCode】29、两数相除
算法·leetcode·职场和发展
船厂电气自动化ai大模型3 小时前
AI大模型与数学/第63课:矩阵定义、矩阵加法、标量乘法(逐级精讲)
数据结构·人工智能·深度学习·线性代数·算法
余额瞒着我当琳3 小时前
算法修炼 chapter 2 双指针进阶、盛最多水的容器、有效三角形的个数、两数之和、三数之和、四数之和
算法
你压到我腿毛了6663 小时前
C语言冒泡算法(Bubble sort)
c语言·数据结构·算法
靠沿4 小时前
贪心算法专题(三)
算法·贪心算法
super大力张4 小时前
MOE基于结构的药物设计(七):Ligand R-Vectors——如何判断配体可以从哪里继续生长?
数据库·算法·cadd·moe·svl·基于结构的药物设计