主循环就是一节一节的处理,循环变量为当前节的开始结点p,终止条件为p==NULL。需要维护的变量是left outer 结点 prev。
主循环体逻辑:
1)从p往后走k步,定位到right outer 结点 q,如果走不到k步链表结束了,最后一组不到k个,不reverse,所有组处理完毕,break。
2)头插法reverse 组内结点,从第二个结点开始插,头插发的两个主要变量 head2 和 next 分别用 prev->next 域和 firstNode->next域存储。
3)为下一次循环更新prev= firstNode。
ListNode *reverseKGroup(ListNode *head, int k)
{
ListNode dummy(-1), *prev= &dummy;
dummy.next= head;
for(auto p = head; p; )
{
int i=0;
auto q =p;
for(; q && i<k; i++)
q=q->next;
if(i<k) break; //last group less than k, don't reverse and all groups done
ListNode * const firstNodeInGroup=p;
for(p=p->next; p!=q; )
{
firstNodeInGroup->next = p->next; //first node's next field as next variable
p->next=prev->next; //use left outer node's next field as the head2 variable
prev->next = p;
p= firstNodeInGroup->next;
}
prev= firstNodeInGroup;
}
return dummy.next;
}
一个更简单版本的:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy(-1), *prev = &dummy;
dummy.next = head;
for (ListNode *q, *p; head; prev = head, head = q) {
int i = 0;
for (q = head; i < k && q; ++i) q = q->next;
if (i < k) break;
for (p = head, prev->next = q; p != q; ) {
auto next = p->next;
p->next = prev->next;//prev->next as the head2 variable
prev->next = p;
p = next;
}
}
return dummy.next;
}
不过还是推荐递归版本的,因为逻辑清晰
ListNode* reverseKGroup(ListNode* head, int k) {
int i = 0;
auto p = head;
for (; i < k && p; ++i, p = p -> next);
if (i < k) return head;
ListNode* head2 = nullptr;
for (auto q = head; q != p;) {
auto next = q -> next;
q -> next = head2;
head2 = q;
q = next;
}
head -> next = reverseKGroup(p, k);
return head2;
}