这道题关于链表的操作,中间指针操作略复杂。
/**
* 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* p=head;//用来遍历链表的指针
ListNode* headpre= new ListNode(-1);//翻转后的链表头部之前的指针,用来返回反转后的head;
headpre->next=head;//当链表长度不足k时,确保返回正确值;
ListNode* pre=headpre;//pre为翻转一小段长度为k的部分时,之前已经翻转好的链表的尾部节点的指针
//每次从p开始向后遍历k个节点,如果p之后节点不足k个,此时flag为1,则break;
//如果p之后节点足够,那么这段长为k的链表首尾分别为[curtail, curhead],对子段进行翻转即可;
while(p!=NULL){
//如果从p往后有k个节点则继续计算,否则return;
//寻找界定的指针[curtail, p2, p3, ... , curhead] p,即p为curhead的下一个节点;
//curtail和curhead分别为将要翻转部分的头和尾(此处curtail和curhead按反转之后的顺序标记头尾)
ListNode* curtail=p;
int flag=0;
for(int i=1;i<k;i++){
p=p->next;
if(p==NULL) {flag=1;break;}
}
if(flag) break;
ListNode* curhead=p;
p=p->next;
//然后翻转curt与curh之间的节点;
ListNode* pcur=curtail;
ListNode* pnext=curtail->next;
while(pcur!=curhead){
ListNode* tmp=pnext->next;
pnext->next=pcur;
pcur=pnext;
pnext=tmp;
}
//让已经翻转好的部分的尾部指针pre指向刚刚翻转好的这段的头部指针;
//让刚刚翻转好的这段的尾部指针指向后面未反转部分的第一个节点;
//更新pre为curtail;
pre->next=curhead;
curtail->next=p;
pre=curtail;
}
return headpre->next;
}
};
改进一下代码:
/**
* 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* headpre=new ListNode(-1);
headpre->next=head;
ListNode* p=head;
ListNode* pre=headpre;
while(p!=NULL){
//获取头尾
ListNode* left=p;
int flag=0;
for(int i=0;i<k-1;i++){
p=p->next;
if(p==NULL){ flag=1;break;}
}
if(flag) break;
ListNode* right=p;
p=p->next;
//进行翻转
ListNode* cur=left;
ListNode* next=left->next;
while(cur!=right){
ListNode* tmp=next->next;
next->next=cur;
cur=next;
next=tmp;
}
pre->next=right;
pre=left;
left->next=p;
}
return headpre->next;
}
};