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

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

相关推荐
Navigator_Z3 小时前
LeetCode //C - 1289. Minimum Falling Path Sum II
c语言·算法·leetcode
CCblandy4 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
mmmmath_34 小时前
LeetCode.104.二叉树的最大深度
数据结构·leetcode
YangYang9YangYan5 小时前
2027供应链计划校招:数学与应用数学专业如何把预测模型讲成业务决策?
人工智能·sql·算法
jsjzsl25 小时前
递归自改进系统(RSI)的本质是自发对称破缺:智能爆炸有界—— AI研发切记盲目投入
人工智能·python·算法
程序员清风5 小时前
最短路径算法:BFS、Dijkstra 与 Floyd
java·算法·宽度优先
梦帮科技5 小时前
Kali Linux Scapy 畸形报文构造学——深度解剖非法 TCP Flags 与反常序列号
linux·爬虫·神经网络·算法·数学建模·系统架构·模拟退火算法
171320330计算机毕设编程7 小时前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
姜鱼问生7 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构