文章目录
🔥 个人主页:铁皮哥(欢迎关注)
📌 作者简介:28届校招生,后端开发/Agent 方向在学
📚 学习内容:Java、Python、计算机视觉、大语言模型、Agent开发
📝 专栏内容:从零开始的Claude Code零代码生活(持续更新中)
✨不只背八股,更想搞懂为什么这样设计
前言
这道题总是容易卡住,关键是指针有点多,需要考虑的边界有点多,记录一下。
一、题目分析
这道题看上去和 LeetCode 206. 反转链表很相似,实际上 206 就是本题当 k = 链表长度时的情况。
本题核心难点不是"反转链表",而是如何按组反转,并把每一组和前后链表重新接好。

我们可以把链表分成若干段:
上一段尾部 -> [当前要翻转的 k 个节点] -> 下一段头部
每次只处理一组长度为 k 的区间。
假设当前链表是:
dummy -> 1 -> 2 -> 3 -> 4 -> 5
如果 k = 3,当前要翻转的是:
1 -> 2 -> 3
翻转后变成:
3 -> 2 -> 1
然后重新接回原链表:
dummy -> 3 -> 2 -> 1 -> 4 -> 5
这里有几个关键指针:
groupPrev:当前组前一个节点
kth:当前组第 k 个节点
groupNext:当前组后面的第一个节点
二、解法
题目最终要返回头节点,我们先在 head 前自行接一个 dummy 节点,最后我们返回的答案就是 dummy.next
java
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
return dummy.next;
}
}
来看之前提到的关键指针 groupPrev,最开始应该被这样初始化,因为第一组的前一个结点就是 dummy。
java
ListNode groupPrev = dummy;
下一步我们要扩一个大循环,在里面完成 k 个一组的翻转链表,具体是这样的思路:
java
while(true){
//1. 找到当前翻转组的第 K 个结点,即关键结点 kth
//第 K 个结点的下一个结点就是关键结点 groupNext
//2.按照力扣 206 的思路去翻转从 groupPrev.next 到 kth 的链表
//3.把翻转后的链表正确接回原链表
}
先来实现找到第 k 个结点的方法,这里很简单,就是逐层 k--,直到 k = 0 或 node 先变成 null 的时候退出。要考虑:node == null 其实就意味着剩余结点数量已经不足 k 个了,可以退出主函数中的大循环了。
java
private ListNode getKth(ListNode node, int k){
while(node != null && k != 0){
node = node.next;
k--;
}
return node;
}
所以循环 while(true) 的终止条件,肯定是当剩余链表的数量已经不足 k 个时退出,可以写成这样:
java
ListNode kth = getKth(groupPrev, k);
if(kth == null){
break;
}
下一步去翻转从 groupPrev.next 到 kth 的链表。
groupNext 的语义是当前组的下一个结点。
其他操作就和力扣 206 的思路是一样的,唯一不同的是 while 的终止条件不是 cur != null,而是 cur != groupNext,这是因为我们最多只能翻转 k 个结点,如果终止条件设为 cur != null,那就会翻转从当前一直到尾部的所有结点了。
java
ListNode groupNext = kth.next;
ListNode prev = groupNext;
ListNode cur = groupPrev.next;
while(cur != groupNext){
ListNode temp = cur.next;
cur.next = prev;
prev = cur;
cur = temp;
}
翻转完这 k 个结点后,下一步是把当前处理好的结点组接回原链表。
oldGroupHead指向的是"翻转前"的当前组的头结点,目前已经变成了当前组的尾结点,先把这个值暂存起来。
kth经过翻转,已经从原先的尾结点变成了当前组的新头结点,所以groupPrev.next = kth的意思是:让该组前一个节点的next指向这个新的头结点。然后再把
groupPrev移动到之前暂存的oldGroupHead,因为它现在是当前组的尾结点,下一轮要从它后面继续处理。
java
ListNode oldGroupHead = groupPrev.next;
groupPrev.next = kth;
groupPrev = oldGroupHead;
最终整体代码呈现如下:
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode groupPrev = dummy;
while(true){
ListNode kth = getKth(groupPrev, k);
if(kth == null){
break;
}
ListNode groupNext = kth.next;
ListNode prev = groupNext;
ListNode cur = groupPrev.next;
while(cur != groupNext){
ListNode temp = cur.next;
cur.next = prev;
prev = cur;
cur = temp;
}
ListNode oldGroupHead = groupPrev.next;
groupPrev.next = kth;
groupPrev = oldGroupHead;
}
return dummy.next;
}
private ListNode getKth(ListNode node, int k){
while(node != null && k != 0){
node = node.next;
k--;
}
return node;
}
}

写在文后
期待您的一键三连!如果有什么问题或建议欢迎在评论区交流!