给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
思路:
和原地反转链表的算法思路基本一致,每k个节点调用一次原地反转的算法。唯一的难点是衔接每段反转好的链表。如例子中的1->4,3->5。解决方法是多设置一个指针tail记录前一个反转好的链表的尾部。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* next;
ListNode* s=head;
ListNode* end=head;
ListNode* tail=s;
bool flag=false;
while(end!=NULL){
for(int i=1;i<k;i++){
//如果不足,则不需要反转,但需要将前一段的tail接到该段的开头
if(end==NULL) {
tail->next=s;
return head;
}
end=end->next;
}
//特殊情况,最后一段正好差一个,循环会正常结束,但不需要反转
if(end==NULL) {
tail->next=s;
return head;
}
//flag表示是否是第一段,如果是的话不需要处理tail,tail的处理要从第二段反转结束后才开始。但需要处理head。
if(flag){
tail->next=end;
tail=s;
}
else{
head=end;
}
//反转的区间是[s,end],next指向下一个待反转段的开头
next=end->next;
end->next=NULL;
reverse(s);
flag=true;
s=next;
end=next;
}
return head;
}
//反转链表
void reverse(ListNode* head){
ListNode* p1=NULL;
ListNode* p2=head;
ListNode* p3=head->next;
while(p2!=NULL){
p2->next=p1;
p1=p2;
p2=p3;
if(p3!=NULL) p3=p3->next;
}
}
};