链表类的题都是那几步比如断链、接链、反转、排序的操作而已。难题也只不过是简单题的组合或者几个简单的思路的组合而已。
ListNode* reverseKGroup(ListNode* head, int k) {
if (!head || !head->next || k == 1) return head;
ListNode *dummyhead = new ListNode(-1); // 虚拟头节点
dummyhead->next = head;
ListNode *pos = dummyhead, *tail = dummyhead;
while (tail)
{
for (int i = 0; i < k&&tail; ++i) tail = tail->next; // 用于定位每个拥有k个元素的sub链表的最后一位
if (!tail) return dummyhead->next; // 假如i还没加到k,tail就到头了,那就结束while循环
ListNode *afterPos = pos->next; // afterPos用于定位每个拥有k个元素的sub链表的第一位
ListNode *afterTail = tail->next; // afterTail用于定位每个拥有k个元素的sub链表的最后一位的下一位,因为要把链表接回去
tail->next = nullptr; // 断链操作,把拥有k个元素的sub链表从主链表中断开,好做反转处理
pos->next = reverseOneList(afterPos); // 把反转好的链表接到pos后面(所以pos就是每个拥有k个元素的sub链表的第一位的前一位)
afterPos->next = afterTail; // 接链,反转之后,afterPos变成了sub链表的最后一位,把它和后面的链表接回去
pos = afterPos; // pos重新回到下一个拥有k个元素的sub链表的第一位的前一位
tail = pos; // tail也是。因为一开始,tail和pos都在同一个位置(一开始是都在dummyhead)
}
return dummyhead->next;
}
ListNode *reverseOneList(ListNode *head)
{
// 反转链表。参考leetcode #206(简单题)
if (!head || !head->next) return head;
ListNode *prev = nullptr, *curr = head;
while (curr)
{
ListNode *nextptr = curr->next;
curr->next = prev;
prev = curr;
curr = nextptr;
}
return prev;
}