25. Reverse Nodes in k-Group
题目大意
Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is.
You may not alter the values in the list’s nodes, only nodes themselves may be changed.
中文释义
给定一个链表的头节点,每次反转 k 个节点,并返回修改后的链表。
k 是一个正整数,且小于或等于链表的长度。如果节点数不是 k 的倍数,则最后剩下的节点应保持原样。
你不能更改链表节点中的值,只能更改节点本身。
示例
Example 1:
Input: head = [1,2,3,4,5]
, k = 2
Output: [2,1,4,3,5]
Example 2:
Input: head = [1,2,3,4,5]
, k = 3
Output: [3,2,1,4,5]
限制条件
- 链表中的节点数为 n。
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶问题
你能在 O(1) 额外内存空间中解决这个问题吗?
解题思路
方法
即在给定的单链表中每 k 个节点为一组进行反转。该方法使用迭代方式。
-
边界条件检查:
- 如果头节点
head
为空或k
为 1,直接返回head
。
- 如果头节点
-
使用哨兵节点:
- 创建一个哨兵节点
sentinel
并将其next
指向head
。
- 创建一个哨兵节点
-
初始化指针和计数:
- 创建指针
pre
指向哨兵节点,cur
指向head
。初始化计数变量count
。
- 创建指针
-
计算节点总数:
- 遍历链表,计算节点总数并存储在
count
中。
- 遍历链表,计算节点总数并存储在
-
按组反转节点:
- 当
count
大于等于k
时,进行反转操作:- 将
cur
设置为pre
的下一个节点。 - 对每个分组内的节点进行反转:
- 通过迭代更新
cur
和nex
(cur
的下一个节点)的next
指针,将节点逐个插入到pre
的后面。
- 通过迭代更新
- 更新
pre
为当前分组反转后的最后一个节点。 - 减少
count
以处理下一个分组。
- 将
- 当
-
返回结果:
- 最后返回哨兵节点
sentinel
的next
作为结果,同时删除哨兵节点防止内存泄漏。
- 最后返回哨兵节点
代码
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if (head == nullptr || k == 1) return head;
ListNode *sentinel = new ListNode(0);
sentinel->next = head;
ListNode *pre = sentinel, *cur = head, *nex;
int count = 0;
while (cur) {
count++;
cur = cur->next;
}
while (count >= k) {
cur = pre->next;
nex = cur->next;
for (int i = 1; i < k; ++i) {
cur->next = nex->next;
nex->next = pre->next;
pre->next = nex;
nex = cur->next;
}
pre = cur;
count -= k;
}
ListNode *result = sentinel->next;
delete sentinel; // 防止内存泄漏
return result;
}
};