D

当前:LC206 · 反转链表:如何不丢掉后半段链表 · 首次出现于 Day 9 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

LC206

反转链表:如何不丢掉后半段链表

三指针反转 · 先保存 next 再改 cur.Next

LC206 的核心不是「把箭头反过来」,而是在修改 cur.Next 之前,必须先把原来的后继保存到 next。否则后半段链表会永远失联。

链表 · 三指针先保存 nextO(n) · O(1)
输入
1 2 3 4 5
输出
5 4 3 2 1

边界测试 · 切换后整段动画会重算

1/14Scene 1
当前步骤

步骤 1:题目 · 反转 1→2→3→4→5

LC206 的核心不是「把箭头反过来」这么简单。真正要小心的是:在修改 cur.Next 之前,必须先把原来的后继保存到 next 里,否则后半段链表会永远失联。

输入 1→2→3→4→5 · 目标 5→4→3→2→1

三区状态

已反转区(prev 开头)
nil
未处理区(cur 开头)
1→2→3→4→5→nil
临时保护(next)
prev 已反转cur 当前next 保护

指针现场

1cur2345nil

读题:单链表原地反转,O(n) 时间 O(1) 额外空间

代码 · 当前高亮行随帧切换

1func reverseList(head *ListNode) *ListNode {
2 var prev *ListNode
3 cur := head
4
5 for cur != nil {
6 next := cur.Next
7 cur.Next = prev
8 prev = cur
9 cur = next
10 }
11
12 return prev
13}

不变量 · 算法为什么对

  • · prev 指向已反转好的前缀链表头。
  • · cur 指向待反转的第一个节点。
  • · next 临时保存 cur 原来的后继,改指针前必须赋值。
  • · 每轮顺序:保存 next → 改 cur.Next → prev/cur 右移。

时间线 · 点击跳转

执行轨迹表

点击行跳转
stepprev 链cur 链next当前动作
1nil1→2→3→4→5→nilnil读题:单链表原地反转,O(n) 时间 O(1) 额外空间
2nil1→nilnil错误:跳过 next := cur.Next,直接改 cur.Next
3nil1→nil(已断)nil断链:head 只能到 1→nil,2→3→4→5 成孤岛
4nil1→2→3→4→5→nilnil策略:next 临时保存 cur 原来的后继
5nil1→2→3→4→5→nilnil初始化三指针
6nil1→2→3→4→5→nil2第一拍:next = cur.Next
7nil1→nil2第二拍:cur.Next = prev
81→nil2→3→4→5→nilnil第三拍:prev=cur; cur=next
102→1→nil3→4→5→nil4第 2 轮三拍完成:先保存 next,再改指向,再右移
113→2→1→nil4→5→nil5第 3 轮三拍完成:先保存 next,再改指向,再右移
124→3→2→1→nil5→nilnil第 4 轮三拍完成:先保存 next,再改指向,再右移
135→4→3→2→1→nilnilnil第 5 轮三拍完成:先保存 next,再改指向,再右移
135→4→3→2→1→nilnilnilcur 为空,循环结束
145→4→3→2→1→nilnilnil返回 prev 作为新 head
面试怎么说

这题用三个指针。prev 表示已经反转好的链表头,cur 表示当前处理节点,next 临时保存 cur.Next,防止修改指针后丢失后半段。每轮先保存 next,再让 cur.Next 指向 prev,然后 prev 和 cur 右移。cur 为空时,prev 就是新头。时间 O(n),空间 O(1)。