1. 链表翻转问题概述
链表翻转是数据结构与算法中的经典问题,而"每k个一组翻转"则是基础问题的进阶版本。这个问题要求我们保持链表原有结构的同时,仅对其中每k个连续节点进行局部翻转。听起来简单,但实际处理时需要兼顾多种边界条件和指针操作细节。
我在第一次面试中遇到这个问题时,花了近40分钟才写出一个漏洞百出的版本。后来在真实项目中使用类似逻辑处理日志分块反转时,才真正理解其中的精妙之处。这个算法不仅考察对指针操作的理解,更是对代码鲁棒性的绝佳检验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与核心思路
2.1 问题定义与示例
给定一个单链表和正整数k,要求将链表中的节点每k个一组进行翻转。如果节点总数不是k的整数倍,则保持最后剩余节点的原始顺序。例如:
输入:1->2->3->4->5->6->7->8,k=3
输出:3->2->1->6->5->4->7->8
这个示例清晰地展示了三组翻转(1-2-3变为3-2-1,4-5-6变为6-5-4)和最后不足k个节点保持原样(7-8)的情况。
2.2 关键难点解析
处理这个问题需要解决几个核心难点:
- 如何准确找到每组k个节点的边界
- 翻转时如何正确处理指针关系避免链表断裂
- 如何处理不足k个节点的尾部情况
- 如何连接各个翻转后的子链表
最易出错的是指针操作顺序。我曾在一个生产环境bug中发现,错误的指针操作会导致链表成环或者节点丢失。比如在翻转a->b->c时,如果先断开a->b的链接而没有保存b的引用,就会永久丢失后续节点。
3. 实现方案与代码解析
3.1 基础翻转算法改进
我们先回顾单链表整体翻转的经典实现:
python复制def reverse_list(head):
prev = None
while head:
next_node = head.next
head.next = prev
prev = head
head = next_node
return prev
基于这个模板,我们需要增加分组逻辑和子链表连接机制。核心思路是:
- 遍历链表,计数k个节点为一组
- 记录该组的头节点(head)和尾节点后的第一个节点(next_head)
- 断开该组与后续链表的连接
- 翻转该子链表
- 将翻转后的子链表重新接入主链表
3.2 完整实现代码
以下是带详细注释的Python实现:
python复制def reverseKGroup(head, k):
# 创建哨兵节点简化边界处理
dummy = ListNode(0)
dummy.next = head
prev = dummy
while True:
# 检查剩余节点是否足够k个
next_head = prev
for _ in range(k):
next_head = next_head.next
if not next_head:
return dummy.next
# 记录当前组头节点和下一组头节点
curr_head = prev.next
next_group_head = next_head.next
# 断开当前组与后续链表的连接
next_head.next = None
# 翻转当前组
reversed_head = reverse_list(curr_head)
# 将翻转后的子链表接回主链表
