Problem statement 给你一个链表,每 k 个节点一组进行翻转,返回修改后的链表。k 是一个正整数,小于等于链表长度。如果节点总数不是 k 的整数倍,最后剩余的节点保持原样。不能修改节点的值,只能改节点指向。要求 O(1) 额外空间。
Example: head = [1,2,3,4,5], k=2 → [2,1,4,3,5] / k=3 → [3,2,1,4,5]
My Solution 思路 先处理特殊情况:空链表或 k=1 直接返回。建哑节点接在 head 前。每次翻转前从当前节点往后数 k 个,不够 k 就说明到了最后一组不足量的尾巴,退出循环。
翻转部分用头插法:遍历 k 个节点,逐个摘下插入 reversed 链。翻完后 reversed 是新头,原来的第一个节点变成了尾。用 prevGroup 保存上一组的尾节点,翻完一组后:prevGroup 指向新头(reversed)、新尾指向剩余节点(cur)、prevGroup 移动到新尾。简化为三步——数 k 个、翻 k 个、接回去。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : ListNode* reverseKGroup (ListNode* head, int k) { if (!head || k == 1 ) return head; ListNode dummy (0 ) ; dummy.next = head; ListNode* prevGroup = &dummy; while (prevGroup->next) { ListNode* end = prevGroup->next; int i = 0 ; while (end && i < k) { end = end->next; i++; } if (i < k) break ; ListNode* cur = prevGroup->next; ListNode* reversed = nullptr ; for (int j = 0 ; j < k; j++) { ListNode* nxt = cur->next; cur->next = reversed; reversed = cur; cur = nxt; } ListNode* oldHead = prevGroup->next; prevGroup->next = reversed; oldHead->next = cur; prevGroup = oldHead; } return dummy.next; } };
哑节点统一处理头部翻转问题。头插法是反转单链表的标准写法,不需要单独写 reverse 函数。关键是翻转后保持前后连接不断掉。