23、反转链表

2 阅读2分钟

206. 反转链表

一句话本质

让每个节点"回头"指向前驱:迭代用 pre/cur/nxt 三指针逐个改向;递归在回溯时 head.next.next = head

链接 leetcode.cn/problems/re…

题目

反转单链表,返回新头节点。要求用迭代和递归两种方式实现。

思路(两种写法)

1. 迭代三指针(本题代码)

pre 记住前驱(初始 None),cur 当前节点,nxt 暂存后继。

  • nxt = cur.next 必须提前存:一旦 cur.next = pre 改了指向,原来的后继就找不回来了,链表直接断掉。
  • 然后 pre = cur; cur = nxt 整体前移。循环结束 pre 停在原尾节点 = 新头。

2. 递归(回溯时反转)

  • 出口not head or not head.next → 返回 head(空链表/单节点天然完成反转)。
  • 递归下去直到尾节点,返回值 = 反转后的新头(原尾节点),一路原样传上来。
  • 反转动作发生在回溯时(后序遍历):
    • head.next.next = head —— 让后继指回自己;
    • head.next = None —— 断掉原链,防成环。

关键卡点

我当时卡在这

  • 迭代的 while 循环推进逻辑(nxt 暂存 → 改向 → 前移)想得最久,其实就三行固定顺序。
  • 递归的两个回溯操作缺一不可:只做 head.next.next = head 不断链,尾节点会自环。
  • 边界无需特判:while cur 天然跳过空链表;单节点链表走一遍循环自然结束。

代码

# 迭代
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        cur = head
        while cur:
            nxt = cur.next      # 1. 存住去路
            cur.next = pre      # 2. 掉头
            pre = cur           # 3. 前移
            cur = nxt
        return pre

# 递归
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head
        new_head = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return new_head

复杂度

  • 迭代:时间 O(n),空间 O(1)
  • 递归:时间 O(n),空间 O(n)(递归栈)

一句话记忆点

下次看到类似题

"反转链表 → 迭代三指针:存去路、掉头、前移;递归回溯:后继指回自己再断原链。"

相似题 / 套用模板

    1. 反转链表 II(反转中间一段,三指针加个前哨)
    1. 两两交换链表中的节点(成对反转,同款改向)
    1. K 个一组翻转链表(分组反转,进阶难)
    1. 回文链表(反转后半段再比对)