题目重点:先实现整链反转,再反转每 k 个节点,保留不足 k 的尾组。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练单链无环,k 为正整数,不复制节点;不足 k 的尾组保持原序。
解题路线
- 整链反转维护 previous/current/following,改当前 next 前先保存 following。局部更新始终保留尚未处理链。
- 分组使用 dummy 和 before,先前进 k 步确认完整组,确定 last 与 after;不完整时直接返回,避免翻一半才发现不足。
- 把 previous 初始化为 after,在组内反向链接,使旧组头自然指向后续链;before.next 接 last,before 移到旧组头。
- 正确性来自已完成前缀顺序正确、before 指向其尾、后缀未改;一次翻组后重新满足不变量。
手动走一遍
1→2→3→4→5,k=2 得2→1→4→3→5;k=3 得3→2→1→4→5;k=1原序。整链反转从1→2→3变3→2→1,尾 next 必须 None。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
class Node:
def __init__(self, value, next=None):
self.value, self.next = value, next
def reverse(head):
previous = None
while head:
following = head.next
head.next = previous
previous, head = head, following
return previous
def reverse_k_group(head, k):
"""Reverse complete groups only; preserve a short final group. Acyclic input."""
if k < 1:
raise ValueError('k must be positive')
dummy = Node(None, head)
before = dummy
while True:
last = before
for _ in range(k):
last = last.next
if last is None:
return dummy.next
after = last.next
current, previous = before.next, after
while current is not after:
following = current.next
current.next = previous
previous, current = current, following
old_first = before.next
before.next = last
before = old_first
复杂度
O(n) 时间、O(1) 工作空间;每完整组定位和翻转各至多 k 步,无递归深度风险。
易错点与追问
容易失分的边界
- 先改 next 再保存后继。
- 尾组不足时仍翻转。
- 新组尾接错产生环。
继续深挖
- 不足 k 也反转时怎么改?
- 如何证明复用节点且没有丢失?
