BM1 反转链表¶
简单通过率 40.22%python3核心代码模式样例通过牛客 AC链表
讲解章节:链表
一句话
把单链表每条边的指向掉个头,返回原来的尾节点作为新表头。
解题思路¶
这题考什么¶
链表反转的本质是改边的方向,不是搬运节点值。把链表看成一串单向的边, 反转就是逐条边取反,节点对象一个都不用新建,val 一个都不用动。 链表的结构与指针搬移见 链表。
维护两个指针:prev 指向「已经反转好的那一段的头」,cur 指向「还没处理的那一段的头」。 每一轮做四件事,顺序不能乱:
循环不变量是「prev 是反转好的那段的头,cur 是原顺序剩余段的头,两段无交集」。 cur 变成 None 时剩余段为空,prev 正好停在原链表的最后一个节点,也就是新表头。
数据规模与复杂度¶
n <= 1000,其他语言时限 2 秒。一趟遍历 O(n) 时间、O(1) 额外空间, 最坏也就一千次指针赋值,量级上没有任何压力。 另一条思路是把 val 收进列表再倒序建新链,时间同样 O(n), 但要多开 O(n) 空间、多造 n 个节点对象,不满足题面「空间复杂度 O(1)」。
坑在哪¶
nxt = cur.next必须写在cur.next = prev之前。顺序反过来, cur.next 已经被覆盖成 prev,nxt 拿到的是前一个节点,链表当场退化成 两个节点来回打转,循环再也走不到 None;- 返回值是 prev 不是 cur。循环退出时 cur 已经是 None,返回 cur 等于交了个空链表;
- 空链表与单节点不必特判:head 为 None 时 while 一次都不进,返回 prev = None, 对应样例二的空表;单节点进一次循环,它的 next 被置成 None 后原样返回。
样例复核¶
输入 {1,2,3}。第一轮:1.next = None,prev = 1,cur = 2; 第二轮:2.next = 1,prev = 2,cur = 3;第三轮:3.next = 2,prev = 3,cur = None。 返回 prev = 3,整条链是 {3,2,1},与样例一致。
参考实现¶
[:octicons-arrow-left-16: PIO18](PIO18.md) [BM2 :octicons-arrow-right-16:](BM2.md)