这道题太难了,想了一会没思路直接去看灵神的题解了。灵神的思路还是很容易理解的,通过一个二重循环来实现k个一组反转链表,外层循环用于控制局部反转的次数,内层循环用于反转局部k个节点,在内层循环中,反转的思路和206.反转链表是一致的,这个我之前写过文章,反转的逻辑可以参考这个,下面简单演示一个节点个数为7
,k = 3
的推演过程。
值得注意的是,我们在完成一次局部反转后,pre
指针和current
指针分别指向原链表中k小组的最后一个节点和下一个k小组的第一个节点,我们只需要将反转过后的局部链表的第一个节点和最后一个节点的指向关系处理好就行,然后再移动虚拟头节点即可,为下一次局部反转做准备,至于在此后的局部反转中,pre指针初始状态下指向哪里,我们是不关心的,因为在局部反转之后,我们会对反转过后的局部链表的首节点和尾节点的指向进行专门的处理(得益于虚拟头节点的存在),不用担心pre初值的指向带来的隐患。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//统计链表长度
int length = 0;
ListNode* current = head;
while(current){
length++;
current = current -> next;
}
ListNode* virtual_head = new ListNode(0, head); //定义虚拟头节点
ListNode* temp = virtual_head;
ListNode* pre = nullptr;
current = temp -> next;
for(; length >= k; length -= k){ //外层循环控制局部反转的次数
for(int i = 0; i < k; ++i){ //内层循环执行局部的k个节点的反转
ListNode* nxt = current -> next;
current -> next = pre;
pre = current;
current = nxt;
}
ListNode* nxt = temp -> next;
temp -> next = pre;
nxt -> next = current;
temp = nxt;
}
return virtual_head -> next;
}
};