https://leetcode.cn/problems/reverse-nodes-in-k-group/description/
一、题目解析
1.1 题意
给定链表头节点 head 和整数 k,每 k 个节点一组进行反转,返回反转后的链表。如果最后一组不足 k 个,保持原顺序。
输入:1→2→3→4→5, k=2输出:2→1→4→3→5输入:1→2→3→4→5, k=3输出:3→2→1→4→5 (最后两个不足 3 个,不动)核心操作:把链表按 k 个切成段,每段递归反转,再串回去。

二、递归反转模板
先看单链表反转的递归写法——后续分段反转的基础组件。
private ListNode reverse(ListNode head) { // 空链表或到尾节点,直接返回 if (head == null || head.next == null) { return head; } // 递归反转后续链表 ListNode next = reverse(head.next); // 让后继节点回头指向自己 head.next.next = head; // 断开原指针 head.next = null; return next;}反转后,原来的头变成尾(next 为 null),原来的尾变成头(被返回),后面接回主链时会反复用到。
三、分段处理框架
reverseKGroup 的骨架是一个标准的链表分段循环,配合 dummy 节点省掉头节点特判:
dummy → [段1] → [段2] → [段3] → ... ↑ prev(指向已处理部分的尾部)每轮循环做四步:
- 找当前段:
segHead = prev.next(段头),segTail从 prev 出发走 k 步(段尾)。不足 k 个直接 break。 - 切断:
segTail.next = null,把当前段从主链上拆下来。 - 反转:调
reverse(segHead),原来的 segHead 变尾,segTail 变头。 - 接回:
segHead.next = nextHead(旧头接下一段),prev.next = segTail(prev 接新头),prev = segHead(prev 移到当前段新尾)。

四、代码详解
class Solution { // 递归反转单链表,返回新头 private ListNode reverse(ListNode head) { if (head == null || head.next == null) { return head; } ListNode next = reverse(head.next); head.next.next = head; head.next = null; return next; } public ListNode reverseKGroup(ListNode head, int k) { // dummy 哨兵,统一头节点操作 ListNode dummy = new ListNode(-1); dummy.next = head; ListNode prev = dummy; // 指向已处理部分的最后一个节点 while (prev.next != null) { // Step 1:找当前段 ListNode segHead = prev.next; // 当前段的头 ListNode segTail = prev; // 从 prev 开始往后走 k 步找尾 int count = 0; while (segTail.next != null && count < k) { count++; segTail = segTail.next; } // 不足 k 个,不处理 if (count < k) { break; } // Step 2:暂存下一段的头,然后切断当前段 ListNode nextHead = segTail.next; segTail.next = null; // Step 3:递归反转当前段 // 注意:reverse 之后 segHead 变成尾,segTail 变成头 ListNode reversed = reverse(segHead); // Step 4:接回主链 // segHead(旧头,新尾)的 next 指向下一段 segHead.next = nextHead; // prev 的 next 指向 segTail(旧尾,新头) prev.next = segTail; // prev 前进到当前段的新尾(segHead) prev = segHead; } return dummy.next; }}Q:为什么 segTail 变成新头?
A:reverse(segHead) 把从 segHead 到 segTail 这段链表完全反转。反转前 segHead 是头、segTail 是尾;反转后 segHead 变成尾(next 指向 null,也就是之前切断的位置),而 segTail 的 next 被上层递归改成了指向它在原链表中的前驱,最终 segTail 成为新头。所以接回时 prev.next = segTail 把新头接上,segHead.next = nextHead 把新尾接上。
prev 的推进。 处理完一段后,prev = segHead。此时 segHead 是当前段反转后的尾节点,它同时是下一段的前一个节点。下轮循环 prev.next 取到的正好是下一段的头。
不足 k 个时直接 break。 题目要求最后一组不足 k 个保持原样。break 之后 segTail.next = null 那步没执行,剩余节点仍通过 prev.next 连着主链,不会被拆散。
五、复杂度分析
时间 O(n)。每个节点恰好被遍历两轮:一轮在 while 循环里找段尾(count 计数),一轮在 reverse 递归里翻转指针。总操作次数约 2n。
空间 O(k)。递归反转最深 k 层,调用栈深度为 k。
本文由 AgentPlanFlow 生成