LeetCode 876简单链表 · 快慢指针
链表的中间结点 图解题解
这道题到底在问什么
返回链表的中间节点;如果有两个中间节点,返回第二个。
- head
- 1→2→3→4→5→6
- 输出
- 4
最优解:一步一步想明白
- 3可以先统计长度 n,再走 n/2 步。但快慢指针一遍就够。
- 4fast 走过的距离约是 slow 的两倍,所以 fast 到终点时,slow 正好到一半。
- 5startslow 和 fast 都指向头节点 1。
- 6moveslow 到 2,fast 到 3。fast 的速度是 slow 的两倍。
- 7moveslow 到 3,fast 到 5。
- 8stopfast 还能走两步,slow 到 4,fast 走到 null。
- 9answer=4fast 停止时,slow 指向 4,正好是第二个中间节点。
- 10answer=3如果长度是 5,fast 到最后一个节点时停止,slow 指向 3。
- 13偶数长度时,循环条件让 slow 停在第二个中间。
- 16second middle1→2 中,循环走一次后 slow 到 2,fast 到 null,返回第二个中间。
- 23这题学完不要乱跳,下一步去 对应专题 连刷同类题;卡住时用 AI 答疑追问“为什么这一步成立”,比只背答案更稳。
⚠️ 容易写错的地方
✗ 错:while fast.next 写法漏判 fast
✓ 对:while fast and fast.next
fast 可能先变成 null。
✗ 错:偶数长度返回第一个中间
✓ 对:本题返回第二个中间
从 head 同步出发的写法天然返回第二个。
✗ 错:fast 每次只走一步
✓ 对:fast 走两步
速度差才会形成一半位置。
完整代码(Python / C++ / Java)
Python
class Solution:
def middleNode(self, head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slowC++
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};Java
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}套路模板 · 链表的中间结点迁移骨架
# 链表题先固定三件事:dummy、当前指针、下一跳
dummy = ListNode(0)
tail = dummy
while 还有节点要处理:
nxt = 当前节点.next # 改指针前先存后继
tail.next = 选中的节点 # 只改一根箭头
tail = tail.next # tail 必须跟着走
当前指针 = nxt
return dummy.nextListNode dummy(0);
ListNode* tail = &dummy;
while (还有节点要处理) {
ListNode* nxt = cur->next; // 改指针前先存
tail->next = cur; // 接上选中的节点
tail = tail->next; // tail 前进
cur = nxt;
}
return dummy.next;ListNode dummy = new ListNode(0);
ListNode tail = dummy;
while (还有节点要处理) {
ListNode nxt = cur.next; // 改指针前先存
tail.next = cur; // 接上选中的节点
tail = tail.next; // tail 前进
cur = nxt;
}
return dummy.next;复杂度
时间复杂度
O(n)
fast 每轮走两步,总体一遍
空间复杂度
O(1)
只用两个指针
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 链表的中间结点 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
如何返回第一个中间?+
可以调整 fast 初始位置或循环条件,让偶数长度提前停。
这道题为什么用「快慢指针」,换最直接的暴力解会差在哪?+
快慢指针抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。