876. 链表的中间结点

简单 含交互动画

学完这道你应该能: 说清它为什么用「快慢指针」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

返回单链表的中间结点;若有两个中点(节点数为偶数),返回靠后的那个。

输入 = 1 → 2 → 3 → 4 → 5
输出 = 节点 3 (及其之后 3 → 4 → 5)

思路解析

先遍历一遍数出长度 n,再从头走 ⌊n/2⌋ 步定位中点——逻辑没错,但要把链表走两趟。能不能一趟就停在中间?

转折:fast 的速度正好是 slow 的两倍。所以当 fast 走完整条链(约 n 步)时,slow 只走了 n/2 步——天然停在中点。一趟就够,这就是「速度差定位」。

起点 · slow = fast = 头:slowfast 都从头节点 1 出发,重合在一起。下面开始:每一轮 slow 走 1 步、fast 走 2 步,分开移动看得清楚。

第 1 轮 · slow 走 1 步:slow 慢慢来,先走 1 步:1 → 2。fast 暂时还停在头 1,等下它要走两步。

第 1 轮 · fast 走 2 步:fast 一口气走 2 步:1 → 2 → 3。本轮结束:slow 在 2、fast 在 3。fast 把 slow 甩开了,领先正好是 slow 走过距离的两倍。

判循环条件 · fast 后面还有节点:进下一轮前先看条件 while fast and fast.next:fast 在 3,它后面还有 4、5,条件成立,可以再走一轮。

第 2 轮 · slow 走 1 步:slow 走 1 步:2 → 3,来到链表正中。

第 2 轮 · fast 走 2 步到尾:fast 再走 2 步:3 → 4 → 5,落在最后一个节点。此刻 slow 在 3、fast 在 5。fast 想再跨两步就出界了。

fast 到尾 · 循环停 · slow 即中点:关键转折:fast 在 5,它的 next 是 null,循环条件 fast and fast.next 不成立、停止。fast 走完整条链时,slow 只走了一半——slow 正停在 3,返回它及其之后 3 → 4 → 5

偶数个的情况 · 取靠后中点:反向想一下偶数个:若链表只有 1→2→3→4,fast 从头走 2 步到 3、再走 2 步到 null 停,slow 走到 3——返回靠后的那个中点。靠的就是条件 while fast and fast.next,奇偶两种它都处理好了。

快慢指针是链表的万能钥匙:2:1 速度差找中点;同速带固定间距找倒数第 k 个;fast 追 slow 判环。记住「两个指针不同步走」这一招。

参考代码(Python)

Python
1def middleNode(self, head):
2    slow = fast = head
3    while fast and fast.next:     # fast 还能安全跨两步
4        slow = slow.next          # 慢走 1
5        fast = fast.next.next     # 快走 2
6    return slow                   # fast 到尾,slow 在中点

复杂度分析

  • 时间复杂度:O(n) —— fast 走完整条链就停,只一趟
  • 空间复杂度:O(1) —— 只用 slow、fast 两个指针,不存任何节点

套路模板

记住骨架:slow 走 1、fast 走 2、循环条件 fast and fast.next。判环、找环入口、回文链表都是从这个骨架变化而来。

Python
1slow = fast = head
2while fast and fast.next:     # 防 fast.next.next 越界
3    slow = slow.next          # 1
4    fast = fast.next.next     # 2
5# fast 到尾时,slow 在中点(偶数取靠后)

易错点

  • 错误写法:循环条件写成 while fast and fast.next.next正确写法:while fast and fast.next(它决定偶数时取前/后中点:写 fast and fast.next 取靠后(本题要的),写 fast.next and fast.next.next 才取靠前)
  • 错误写法:循环条件只写 while fast正确写法:while fast and fast.next(fast.next 为空时再 .next.next 会空指针报错)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →19. 删除倒数第 N 个结点 ← 返回题库