本题源自LeetCode
--------------------------------------------------------------------
思路:
利用栈结构的解法,时间复杂度O(n),空间复杂度O(k)
1:从左到右遍历链表,如果栈的大小不等于k,就将节点不断压入栈中
2:当栈的大小第一次达到k时,说明第一次凑齐了k个节点进行逆序,从栈中依次弹出
这些节点,并根据弹出顺序依次链接,这一组逆序完成后,需要记录一下新的头部,
同时第一组的最后一个节点(原来是头结点)应该链接下一个节点。
3:步骤2之后,当栈的大小每次达到k时,说明又凑齐了一组应该进行逆序的节点,从
栈中依次弹出这些节点,并根据弹出的顺序重新链接。这一组逆序完成后,该组的第一
个节点(原来是该组最后一个节点)应该被上一组的最后一个节点链接上,这一组的最
后一个节点(原来是该组第一个节点)应该链接下一个节点。然后继续去凑下一组,直
到链表被遍历完成。
代码:
void reverseCore(ListNode* start,ListNode* end,ListNode* &newStart,ListNode* &newEnd){ //用的指针的引用,也可以用 **指针的指针
ListNode* pNext=NULL;
ListNode* p=start;
ListNode* pre=NULL;
newStart=end;
newEnd=start;
ListNode* nextNode=end->next;
while(p!=nextNode){
pNext=p->next;
p->next=pre;
pre=p;
p=pNext;
}
}
ListNode *reverseKGroup(ListNode *head, int k) {
ListNode* p=head;
ListNode* newHead=NULL;
ListNode* start=head;
ListNode* pre=NULL;
ListNode* pNext=NULL;
int count=1;
while(p){
pNext=p->next;
if(count==k){ //节点数量到K 个 反转部分链表
ListNode* newStart=NULL;
ListNode* newEnd=NULL;
reverseCore(start,p,newStart,newEnd);
if(newHead==NULL) //新链表的头指针
newHead=newStart;
if(pre)
pre->next=newStart; //保持链表链接
newEnd->next=pNext;
pre=newEnd; //保存上一个链表的尾节点
start=pNext; //保存每个局部链表的头
count=0; //count清零
}
p=pNext;
count++;
}
return newHead?newHead:head;
}
思路2 :
考虑 用递归即 翻转pairs,翻转x~x+(k-1)之间的节点, x->next = reverseKGroup(x+k,k)
代码:
ListNode* reverseCore(ListNode* start,ListNode* end){ //用的指针的引用,也可以用 **指针的指针
ListNode* pNext=NULL;
ListNode* p=start;
ListNode* pre=NULL;
while(p!=end){
pNext=p->next;
p->next=pre;
pre=p;
p=pNext;
}
return pre;
}
ListNode *reverseKGroup(ListNode *head, int k) {
if(head==NULL||k<2)
return head;
ListNode *p=head;
for(int i=0;i<k;i++){
if(!p)
return head;
p=p->next;
}
ListNode* newHead=reverseCore(head,p); //反转K链表
head->next=reverseKGroup(p,k); //保持链表不断。
return newHead;
}
思路3 非递归
遍历链表,每遍历k个节点,就反转。并且保持链表不断开
ListNode *reverseKGroup(ListNode *head, int k) {
if(head==NULL||k<2)
return head;
ListNode *p=head;
int len=0;
while(p){
p=p->next;
len++;
}
ListNode* root=new ListNode(0);
root->next=head;
ListNode* pre=root;
p=head;
ListNode* pNext=NULL;
for(int i=0;i<len/k;i++){ //循环len/k次
for(int j=1;j<k;j++){ //每次反转k 个节点
pNext=p->next;
p->next=pNext->next;
pNext->next=pre->next;
pre->next=pNext;
}
pre=p; //保持链表不断开
p=p->next;
}
return root->next;
}