第4章|链表

Unit 04 · 两两交换:固定长度局部重写

← Unit 03
仅本次页面有效
U04
Swap Nodes in Pairsprevious · first · second · following

交换的不是两个数值,
而是三条连接关系。

每轮只处理相邻两个节点:先保存这一对之后的入口,再把 previous → first → second → following 改写为 previous → second → first → following。节点对象没有被复制,也没有交换 val。

已恢复本浏览器中的学习进度阶段、动画、代码、脚手架和滚动位置均已恢复。
LeetCode #24 题目模型只能交换节点连接,不能修改节点值

题目要求

给定一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。必须通过修改节点之间的连接完成,不能只交换节点中的数值。

class Solution: def swapPairs( self, head: Optional[ListNode] ) -> Optional[ListNode]: pass

约束与复杂度目标

  • 节点数量范围为 [0, 100];节点值范围为 [0, 100];
  • 奇数长度链表的最后一个节点保持原位;
  • 迭代解法时间复杂度 O(n),额外空间 O(1)。

示例

输入:head = [1,2,3,4]
输出:[2,1,4,3]
输入:head = []
输出:[]
输入:head = [1]
输出:[1]
输入:head = [1,2,3]
输出:[2,1,3]

本页主模型

使用 dummy + previous 固定已完成区域的尾部。每轮获取 first、second 和 following,安全改写三条边。

连接上一题:#92 的“局部头插”缩小为长度固定为 2 的局部改写

Unit 03:局部反转区间

moving = current.next
把 moving 不断插到 before 后面,循环次数由区间长度决定。

→
Unit 04:两两交换

second = first.next
每组只做一次“第二个节点移到第一个节点之前”。

previous

已完成交换区域的最后一个节点。它提供下一组节点的稳定前驱,初始为 dummy。

first

当前一对中的第一个节点,即 previous.next。交换后成为这一对的尾节点。

second

当前一对中的第二个节点,即 first.next。交换后成为这一对的头节点。

following

当前一对后面的第一个节点,即 second.next。必须先保证它仍能被 first 连接。

认知任务 1
把 Unit 03 的局部头插压缩为固定长度为 2 的操作
本题不是一种全新的改边方式。一次交换就是:把 second 从 first 后面摘下,再插到 previous 后面。
四节点局部重写动画状态 1 / 1
previous → first → second → following
→
previous → second → first → following
本步断开 / 覆盖—
本步建立 / 保存—
识别一对
保存 following
first 跳过 second
second 指向 first
previous 接入 second
previous 移到 first
点击下一步,观察节点位置与 next 连接如何分别变化。
错误实验室错误连接会造成成环、重复处理或丢失后缀
先执行 second.next = first

此时 first.next 仍指向 second,会立即形成 first ↔ second 的二节点环。

交换后 previous = second

second 是交换后这一对的头,不是尾。下一轮会从 first 开始,把已处理节点再次纳入。

只检查 previous.next

奇数尾节点可能存在 first,但不存在 second;继续读取 first.next 的字段会破坏边界契约。

关键表达式补全只填写循环边界和三条改边语句
from typing import Optional class Solution: def swapPairs(self, head): dummy = previous = while and : first = second = first.next = second.next = previous.next = previous = return
答案框可拖拽改变高度
代码—节点连接逐行联动状态 1 / 1

当前执行状态

代码行1
previous—
first / second—
following—
链表顺序[1,2,3,4,5]
进入函数。
完成代码联动后进入 #25「K 个一组翻转」官方原题迁移只有代码补全正确或播放完整轨迹后解锁;提示与结构骨架不会直接解锁。

迁移原题:LeetCode #25 K 个一组翻转链表

先完整理解原题,再迁移局部重写。#24 是固定两节点的一次交换;#25 需要先确认剩余节点足够组成完整 K 组,再反转整组并接回主链。

官方原题已核对Hard · Linked List · Recursion · 进阶要求 O(1) 额外空间
打开 LeetCode #25 原题 ↗
#25
K 个一组翻转链表Reverse Nodes in k-Group · Hard

给定链表头节点 head,每 k 个节点一组进行翻转并返回修改后的链表。若最后剩余节点不足 k 个,它们必须保持原有顺序。不能只修改节点值,必须实际改变节点连接。

class Solution:
    def reverseKGroup(
        self,
        head: Optional[ListNode],
        k: int
    ) -> Optional[ListNode]:
        pass

官方示例与约束

head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
  • 1 ≤ k ≤ n ≤ 5000
  • 0 ≤ Node.val ≤ 1000
  • 最后不足 k 个节点保持原顺序。
  • 进阶:使用 O(1) 额外空间。

读题门槛

对于 [1,2,3,4,5]、k=3,节点 4、5 应如何处理?
哪种操作符合题目要求?

#24 → #25:不变的是组级契约,新增的是完整组检查

维度#24 两两交换#25 K 个一组
组大小固定为 2由输入 k 决定
组前驱previousgroup_prev
完整组判断检查 first、second从 group_prev 向后找到 kth
组后入口followinggroup_next = kth.next
组内操作三条边交换两个节点标准反转区间 [组首, group_next)
下一组前驱原 first原组首 group_tail

排列一整组的安全处理顺序

点击卡片。只有先确认完整组并保存右边界,才可以开始修改组内连接。

尚未选择。

语义槽位:先完成状态契约,再看组装代码

槽位 1 · 完整组边界 如何判断剩余节点足够组成一组,并保存组后入口?
槽位 2 · 反转初始化 为什么 previous 必须从 group_next 开始?
槽位 3 · 半开区间反转 组内反转何时停止?
槽位 4 · 接回并推进 反转后如何接回主链并进入下一组?
结构组装结果四个槽位完成后显示
kth = get_kth(group_prev, k)
if kth is None:
    break

group_next = kth.next
previous = group_next
current = group_prev.next

while current is not group_next:
    next_node = current.next
    current.next = previous
    previous = current
    current = next_node

group_tail = group_prev.next
group_prev.next = kth
group_prev = group_tail

官方样例轨迹:[1,2,3,4,5],k=3

group_prevdummy
kth / group_next— / —
previous / current— / —
当前动作准备检查第一组
从 dummy 向后寻找第 3 个节点。
1 / 7

独立重写:不提供完整答案填充

轨迹走到最终状态后,再尝试独立重写。
这里只提供分层提示,不提供完整代码
完成官方轨迹或独立重写后,本页会停留在这里,方便复盘。

Unit 04 Skill 卡

当题目要求按固定大小重写局部链表时,不要让节点“整体跳位置”掩盖改边过程。先命名局部角色,再按安全顺序修改每条边。

触发信号每两个相邻节点交换,且不能修改 val
稳定前驱dummy + previous
局部角色first / second / following
关键顺序first 跳过 → second 回指 → previous 接入
循环不变量previous 是已完成区域尾节点
常见错误先回指成环、previous 移到 second、漏判 second
复杂度时间 O(n),额外空间 O(1)
迁移方向固定 2 个节点 → 固定 K 个节点
下一题#19 删除倒数第 N 个结点
完成后停留在本页 页面不会自动跳转。可以复习局部重写、重播代码轨迹,或手动进入 Unit 05。
手动进入 Unit 05 →
阶段 1 / 6阶段可随时返回;答题后不会自动跳走